Side-by-side regression tables

It’s often helpful to put the results from regression models in a side-by-side table so you can compare coefficients across different model specifications. If you’re unfamiliar with these kinds of tables, check out this helpful guide to how to read them.

We will use the huxreg() function in the huxtable package, the Palmer Penguins dataset, and a few regression models on trying to explain body_mass_g.

library(palmerpenguins)

model1 <- lm(body_mass_g ~ flipper_length_mm, data = penguins)
model2 <- lm(body_mass_g ~ flipper_length_mm + bill_length_mm, data = penguins)
model3 <- lm(body_mass_g ~ flipper_length_mm + bill_length_mm + species, data = penguins)
model4 <- lm(body_mass_g ~ flipper_length_mm + bill_length_mm + species + sex, data = penguins)

huxtable::huxreg()

Installing

huxtable is published on CRAN, so use the “Packages” panel in RStudio to install huxtable, or use:

install.packages("huxtable", dependencies = TRUE)

To knit to Word, you also need the flextable package, so install that too from the “Packages” panel, or use:

install.packages("flextable", dependencies = TRUE)

Using huxtable::huxreg() to knit to HTML and Word works very well.

Basic usage

As you go about building your linear models, you save them as object with different names, e.g., model1, model2, etc. Once you have the models you want to compare, pass them to huxreg():

library(huxtable)

huxreg(model1, model2, model3, model4)
(1)(2)(3)(4)
(Intercept)-5780.831 ***-5736.897 ***-3904.387 ***-759.064    
(305.815)   (307.959)   (529.257)   (541.377)   
flipper_length_mm49.686 ***48.145 ***27.429 ***17.847 ***
(1.518)   (2.011)   (3.176)   (2.902)   
bill_length_mm        6.047    61.736 ***21.633 ** 
        (5.180)   (7.126)   (7.148)   
speciesChinstrap                -748.562 ***-291.711 ***
                (81.534)   (81.502)   
speciesGentoo                90.435    707.028 ***
                (88.647)   (94.359)   
sexmale                        465.395 ***
                        (43.081)   
N342        342        342        333        
R20.759    0.760    0.822    0.871    
logLik-2528.427    -2527.741    -2476.373    -2359.787    
AIC5062.855    5063.482    4964.745    4733.574    
*** p < 0.001; ** p < 0.01; * p < 0.05.

You can add column names, to make the output table more user friendly.

huxreg(list("A" = model1, "B" = model2, "C" = model3, "D" = model4))
ABCD
(Intercept)-5780.831 ***-5736.897 ***-3904.387 ***-759.064    
(305.815)   (307.959)   (529.257)   (541.377)   
flipper_length_mm49.686 ***48.145 ***27.429 ***17.847 ***
(1.518)   (2.011)   (3.176)   (2.902)   
bill_length_mm        6.047    61.736 ***21.633 ** 
        (5.180)   (7.126)   (7.148)   
speciesChinstrap                -748.562 ***-291.711 ***
                (81.534)   (81.502)   
speciesGentoo                90.435    707.028 ***
                (88.647)   (94.359)   
sexmale                        465.395 ***
                        (43.081)   
N342        342        342        333        
R20.759    0.760    0.822    0.871    
logLik-2528.427    -2527.741    -2476.373    -2359.787    
AIC5062.855    5063.482    4964.745    4733.574    
*** p < 0.001; ** p < 0.01; * p < 0.05.

Statistics to display, bold significant variables, add captions

You can choose what statistics to display; for instance, if we wanted to show number of observation, R^2 and adjusted R2, and the residual SE, we pass them to the statistics variable. We can also bold those variables that are significant at, say 0.05, and choose not to use stars to denote level of significance by using stars = NULL.

huxreg(model1, model2, model3, 
                 statistics = c('#observations' = 'nobs', 
                                'R squared' = 'r.squared', 
                                'Adj. R Squared' = 'adj.r.squared', 
                                'Residual SE' = 'sigma'), 
                 bold_signif = 0.05, 
                 stars = NULL
) %>% 
  set_caption('Comparison of models')
Comparison of models
(1)(2)(3)
(Intercept)-5780.831 -5736.897 -3904.387 
(305.815)(307.959)(529.257)
flipper_length_mm49.686 48.145 27.429 
(1.518)(2.011)(3.176)
bill_length_mm     6.047 61.736 
     (5.180)(7.126)
speciesChinstrap          -748.562 
          (81.534)
speciesGentoo          90.435 
          (88.647)
#observations342     342     342     
R squared0.759 0.760 0.822 
Adj. R Squared0.758 0.759 0.820 
Residual SE394.278 394.068 340.114 

Warning 1: huxtable reformats all your tables

If your document creates any other tables (like with tidy()), huxtable automatically formats these tables in a fancy way. If you don’t want that, you can turn it off with this code—put it at the top of your document near where you load your libraries:

# Huxtable likes to automatically format *all* tables, which is annoying. 
# This turns that off.
options('huxtable.knit_print_df' = FALSE)

Warning 2: Knitting to PDF is fragile

In order to knit to PDF, you need to install LaTeX, which you should have done when you installed tinytex. When using huxtable, before knitting to PDF for the first time on your computer, you need to run this in your console to install the LaTeX packages that R uses to knit huxtable tables to PDF:

huxtable::install_latex_dependencies()

If you’re using tinytex, you’ll also need to run this once on your computer:

tinytex::tlmgr_install("unicode-math")