I'm trying to use modelsummary for the following process:
- Estimate a multivariate regression ( j explanatory variables) per group (k groups) so that you have k estimates per each one of j variables.
- Average those k coefficients per each variable and calculate the corresponding t stat.
- Display those averages and t stats in one column as if they were estimates in a normal regression.
Statistically it is not the best approach but that's necessary in this case. It's basically averaged coefficients of k regressions. So my question is for the steps 2 and 3. Here is a reprex using mtcars just to calc averages and tstats:
fit<-mtcars %>% feols(c(mpg,hp )~1)
modelsummary(fit, estimate="{estimate}{stars}", stars = c('*' = .1, '**' = .05, '***'=0.01), output="flextable")
So this is the original ouptut
And I would like to stack those averages and tstats in one column like in the screenshot below.
There are several ways to do this but the best in this case imho would be to say within fixest modelsummary flextable workflow and I haven't been able to find the best approach for this. Would really appreciate any insight!
CodePudding user response:
Usually, I let the flextable
package add footnotes to the results (with flextable::add_footer_lines
) calculated conditionally from another column of p.value
. However, since you are asking the modelSummary package to add "***", you can create the table you want with this code =>
require(tidyverse)
fit<-mtcars %>% fixest::feols(c(mpg,hp )~1)
modelsummary::modelsummary(fit, estimate="{estimate}{stars}",
stars = c('*' = .1, '**' = .05, '***'=0.01),
output="dataframe") %>%
# ↑ change the desired 'output' to "dataframe"
pivot_longer(cols = c(mpg, hp)) %>%
# ↑ transpose the dataframe
filter(part == "estimates" | term == "Num.Obs.") %>%
# ↑ keep only the "estimates" row (from "part"), and the "Num.Obs." row (from var' "term")
arrange(desc(name) ) %>% arrange(part) %>%
# ↑ set the order you want, with Num.Obs in last row
mutate(name = if_else(term == "Num.Obs.", "Num.Obs.", name)) %>%
# ↑ adding a "Num.Obs." label to the variable "name"
select(name, value) %>%
# select only 2 cols
flextable::flextable(cwidth = c(1.5, 2) ) %>%
# ↑ create your table (and indicate the width of your 2 col')
flextable::set_header_labels(values = c("name" = "",
"value" = "(1)")) %>%
# changing the labels, according to your desired output
flextable::merge_v(j = 1:2) %>%
# merge the similar values
flextable::add_footer_lines(values = "*** < .001; ** < .05; * < .1")
# ↑ OPTIONAL: indicate a footnote line, since the modelsummary package add some stars to the results
CodePudding user response:
You can use the shape
argument for this. The ?modelsummary
documentation for this argument is very detailed, and there are also many examples in the vignette here: https://vincentarelbundock.github.io/modelsummary/articles/modelsummary.html#shape
library(fixest)
library(modelsummary)
fit <- mtcars |> feols(c(mpg, hp) ~ 1)
modelsummary(
fit,
shape = model statistic ~ term,
statistic = "statistic",
stars = c("*" = .1, "**" = .05, "***" = 0.01))
(Intercept) | |
---|---|
mpg | 20.091*** |
(18.857) | |
hp | 146.687*** |
(12.103) |
Note: ^^ * p < 0.1, ** p < 0.05, *** p < 0.01
Note that, by default, you won't get the number of observations or other goodness-of-fit statistics at the bottom of the table. This is because it doesn't usually make sense to report a single R2 or number of observations below the results of multiple models.
However, you can easily add those manually using the add_rows
argument.