Using panelsummary with fixest

This vignette focuses on using the panelsummary package with the fixest package. fixest has become one of the most popular regression packages for economists, and therefore further capabilities have been implemented in panelsummary to work seamlessly with fixest. There will be two main capabilities that this vignette covers:

  1. Adding the mean of the dependent variable.
  2. Collapsing fixed effects.

Adding the Mean of the Dependent Variable

To start, load in the fixest, panelsummary, and kableExtra packages.

library(panelsummary)
library(fixest) ## for regressions
library(kableExtra) ## for further table customization

For demonstration purposes, four regressions are estimated with the fixest package using the feols function and the mtcars data:

## estimating two models for mpg
mpg_1 <- mtcars |>
    feols(mpg ~  cyl | gear + carb, cluster = ~hp)
#> NOTE: 0/2 fixed-effect singletons were removed (2 observations).

mpg_2 <- mtcars |>
    feols(mpg ~  cyl | gear + carb + am, cluster = ~hp)
#> NOTE: 0/2/0 fixed-effect singletons were removed (2 observations).


## estimating the same two models for disp
disp_1 <- mtcars |> 
  feols(disp ~ cyl | gear + carb, cluster = ~hp)
#> NOTE: 0/2 fixed-effect singletons were removed (2 observations).

disp_2 <- mtcars |> 
  feols(disp ~ cyl | gear + carb + am, cluster = ~hp)
#> NOTE: 0/2/0 fixed-effect singletons were removed (2 observations).

To create a regression table with two panels (Panel A: MPG/Panel B: Displacement) and two models in each, the lists list(mpg_1, mpg_2) and list(disp_1, disp_2) can be passed into the arguments for .... However, since each of these models is of the class fixest (i.e., created with the fixest package), the mean_dependent argument can be set to TRUE to show the means of the dependent variable in each column:

panelsummary(list(mpg_1, mpg_2), list(disp_1, disp_2), 
             mean_dependent = TRUE,
             panel_labels = c("Panel A: MPG", "Panel B: Displacement"),
             caption = "Automated Mean of Dependent Variable") |> 
  kable_classic(full_width = F, html_font = "Cambria") 
Automated Mean of Dependent Variable
Panel A: MPG
cyl -0.907 -1.093
(0.764) (0.775)
Mean of Dependent Variable 20.273 20.273
Num.Obs. 30 30
R2 0.813 0.831
R2 Adj. 0.765 0.777
R2 Within 0.058 0.088
R2 Within Adj. 0.017 0.046
AIC 156.8 155.8
BIC 166.6 167.0
RMSE 2.61 2.49
Std.Errors by: hp by: hp
FE: gear X X
FE: carb X X
FE: am X
Panel B: Displacement
cyl 43.306 43.905
(12.660) (13.061)
Mean of Dependent Variable 231.237 231.237
Num.Obs. 30 30
R2 0.907 0.907
R2 Adj. 0.882 0.878
R2 Within 0.399 0.401
R2 Within Adj. 0.373 0.373
AIC 317.3 319.2
BIC 327.2 330.4
RMSE 37.97 37.88
Std.Errors by: hp by: hp
FE: gear X X
FE: carb X X
FE: am X

Notice that a new row was placed before the “Num.Obs.” row in each panel with the mean of the dependent variable. This is the default setting. If you would like to change where the mean is placed, you will need to customize using the panelsummary::panelsummary_raw function (see the Adding Rows to a panelsummary Table vignette for more details). Now, using gof_map, the goodness-of-fit statistics will be mapped/renamed. Note that the mean of the dependent variable is not included in the mapped statistics and cannot be reordered without using panelsummary::panelsummary_raw.

## creating a renaming tibble to pass into panelsummary 
gm <- tibble::tribble(
        ~raw,      ~clean,          ~fmt,  ~omit,
        "nobs", "Observations", 0,  FALSE,
        "FE: gear", "FE: Gear", 0, FALSE,
        "FE: carb", "FE: Carb", 0, FALSE,
        "FE: am", "FE: AM", 0, FALSE
)

## creating the regression table
panelsummary(list(mpg_1, mpg_2), list(disp_1, disp_2),
             mean_dependent = TRUE,
             panel_labels = c("Panel A: MPG", "Panel B: Displacement"),
             gof_map = gm,
             caption = "Automated Mean of Dependent Variable-Renamed and Reordered") |> 
  kable_classic(full_width = F, html_font = "Cambria") 
Automated Mean of Dependent Variable-Renamed and Reordered
Panel A: MPG
cyl -0.907 -1.093
(0.764) (0.775)
Mean of Dependent Variable 20.273 20.273
Observations 30 30
FE: Gear X X
FE: Carb X X
FE: AM X
Panel B: Displacement
cyl 43.306 43.905
(12.660) (13.061)
Mean of Dependent Variable 231.237 231.237
Observations 30 30
FE: Gear X X
FE: Carb X X
FE: AM X

Lastly, as an important aside, any models that are not of class fixest will not return a dependent variable mean. There are plans to accommodate more models for this feature in the future.

Collapsing Fixed Effects

Notice that in the tables above that the fixed effects in columns (1) and (2) are the same across each panel. To reduce the number of rows, the collapse_fe argument can be used to show a separate panel containing only the fixed effects. Observe that there is also a warning message returned when this command is used; the warning message is telling the user that the function assumes both panels have the same fixed effects for the same models.

## collapsing fixed effects with collapse_fe = T
panelsummary(list(mpg_1, mpg_2), list(disp_1, disp_2),
             mean_dependent = TRUE,
             panel_labels = c("Panel A: MPG", "Panel B: Displacement"),
             gof_map = gm,
             caption = "Collapsed Fixed Effects",
             collapse_fe = T) |> 
  kable_classic(full_width = F, html_font = "Cambria") |> 
  footnote("Collapsing the fixed effects assumes the fixed effects in all panels are the same!")
#> Warning in panelsummary(list(mpg_1, mpg_2), list(disp_1, disp_2),
#> mean_dependent = TRUE, : panelsummary does not check if the fixed effects in
#> each panel match. It always assumes they do!
Collapsed Fixed Effects
Panel A: MPG
cyl -0.907 -1.093
(0.764) (0.775)
Mean of Dependent Variable 20.273 20.273
Observations 30 30
Panel B: Displacement
cyl 43.306 43.905
(12.660) (13.061)
Mean of Dependent Variable 231.237 231.237
Observations 30 30
FE: Gear X X
FE: Carb X X
FE: AM X
Note:
Collapsing the fixed effects assumes the fixed effects in all panels are the same!

Although it does not appear in HTML, a LaTeX version of this table will include a horizontal line separating the fixed effects from the other panels. This can be switched off using the hline_before_fe argument.