Search code examples
rstargazer

Bug? Stargazer fails to properly display fixed effects/factor labels with "omit" options?


When I generate a table in stargazer and omit fixed effects, then specify the omit.labels option, stargazer (version 5.2.2) shows "No" for every column. Here's an example:

library(stargazer)

# generate example data
set.seed(1)
list_of_states <- rep(c(1, 2, 3, 4, 5), 5)
df <- data.frame("state" = list_of_states, "y" = runif(25),
    "x1" = runif(25), "x2" = runif(25))

# OLS without fixed effects
ols.1 <- glm(y ~ x1, data = df)
ols.2 <- glm(y ~ x1 + x2, data = df)

# OLS with fixed effects
fe.1 <- glm(y ~ x1 + factor(state), data = df)
fe.2 <- glm(y ~ x1 + x2 + factor(state), data = df)

stargazer(ols.1, ols.2, fe.1, fe.2,
  type = "text",
  align = TRUE,
  omit = c("state"),
  omit.labels = c("State FE"))

This outputs

==================================================
                        Dependent variable:       
                  --------------------------------
                                 y                
                    (1)      (2)     (3)     (4)  
--------------------------------------------------
x1                 0.088    0.098   0.151   0.157 
                  (0.241)  (0.264) (0.263) (0.283)

x2                          0.028           0.022 
                           (0.270)         (0.287)

Constant          0.485*** 0.467*  0.466**  0.452 
                  (0.142)  (0.227) (0.215) (0.280)

--------------------------------------------------
State FE             No      No      No      No   
--------------------------------------------------
Observations         25      25      25      25   
Log Likelihood     -5.321  -5.315  -3.528  -3.524 
Akaike Inf. Crit.  14.642  16.630  19.056  21.048 
==================================================
Note:                  *p<0.1; **p<0.05; ***p<0.01

The labels in the "State FE" row should say "Yes" in the last two columns. Is this a bug?


Solution

  • The short answer is that it's a bug. It appears that the intent of the code is to create a matrix that looks something like

    cbind(names(coef(ols.1)), names(coef(fe.1)))
    #      [,1]          [,2]            
    # [1,] "(Intercept)" "(Intercept)"   
    # [2,] "x1"          "x1"            
    # [3,] "(Intercept)" "factor(state)2"
    # [4,] "x1"          "factor(state)3"
    # [5,] "(Intercept)" "factor(state)4"
    # [6,] "x1"          "factor(state)5"
    

    and then check each column for the omit regex. However, what actually happens is something like

    cbind(cbind(NULL, names(coef(ols.1))), names(coef(fe.1)))
    #      [,1]          [,2]         
    # [1,] "(Intercept)" "(Intercept)"
    # [2,] "x1"          "x1"  
    

    which results in the omit term not being found. This happens because, from ?cbind

    When the arguments consist of a mix of matrices and vectors the number of columns (rows) of the result is determined by the number of columns (rows) of the matrix arguments. Any vectors have their values recycled or subsetted to achieve this length.