Yoshi
Yoshi

Reputation: 23

Extracting information from R objects and importing it to a modelsummary table

I am trying to make a statistical model summary table using the modelsummary package.

I ran 6 regressions. I conducted joint hypothesis tests for 2 of them, which include certain variables (specificaly, educ and exper) as explanatory variables. I want to include the F statistics from those tests in the table, but have trouble extracting information from the tests and importing it into the table.

Here are some more details.

(1) What I did, part 1: Packages, data, and analyses

library(tidyverse)
library(wooldridge)   # Data
library(estimatr)     # Estimation
library(car)          # F test
library(modelsummary) # Table
library(kableExtra)   # Table

wage2 <- wage2 %>% 
  mutate(lwage = log(wage))

model1 <- lm_robust(lwage ~ educ, 
                    data = wage2, se_type = "HC1")
model2 <- lm_robust(lwage ~ exper, 
                    data = wage2, se_type = "HC1")
model3 <- lm_robust(lwage ~ educ + exper, 
                    data = wage2, se_type = "HC1")
F3 <- linearHypothesis(model3, test = "F", 
                       c("educ = 0", "exper = 0"))
model4 <- lm_robust(lwage ~ educ + tenure, 
                    data = wage2, se_type = "HC1")
model5 <- lm_robust(lwage ~ exper + tenure, 
                    data = wage2, se_type = "HC1")
model6 <- lm_robust(lwage ~ educ + exper + tenure, 
                    data = wage2, se_type = "HC1")
F6 <- linearHypothesis(model6, test = "F", 
                       c("educ = 0", "exper = 0"))

The results of the joint hypothesis tests are as follows.

F3
## Linear hypothesis test
## 
## Hypothesis:
## educ = 0
## exper = 0
## 
## Model 1: restricted model
## Model 2: lwage ~ educ + exper
## 
##   Res.Df Df      F    Pr(>F)    
## 1    934                        
## 2    932  2 67.715 < 2.2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
F6
## Linear hypothesis test
## 
## Hypothesis:
## educ = 0
## exper = 0
## 
## Model 1: restricted model
## Model 2: lwage ~ educ + exper + tenure
## 
##   Res.Df Df      F    Pr(>F)    
## 1    933                        
## 2    931  2 63.592 < 2.2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

(2) What I did, part 2: Table

regs <- list()
regs[['Model 1']] <- model1
regs[['Model 2']] <- model2
regs[['Model 3']] <- model3
regs[['Model 4']] <- model4
regs[['Model 5']] <- model5
regs[['Model 6']] <- model6

gm <- tribble(
  ~raw, ~clean, ~fmt,
  "adj.r.squared", "$\\bar{R}^2$", 3,
  "nobs", "Sample size", 0
  )

rows <- tribble(
  ~term, ~'Model 1', ~'Model 2', ~'Model 3', 
  ~'Model 4', ~'Model 5', ~'Model 6', 
  '$F$ statstics', '', '', '', '', '', '',
  '$H_0: \\beta_{\\rm{educ}} = 0, \\beta_{\\rm{exper}} = 0$', 
  '', '', '67.715***', '', '', '63.592***',
  '', '', '', '(0.000)', '', '', '(0.000)'
)
attr(rows, 'position') <- c(9:11)

table <- msummary(regs, 
         estimate = "{estimate}{stars}",
         gof_map = gm, 
         notes = list("*** p < 0.01, ** p < 0.05, * p < 0.1. 
                      Heteroskedasticity-consistent 
                      standard errors in brackets. 
                      P values in brackets for F statistics."),
         add_rows = rows) %>% 
  row_spec(c(1, 3, 5, 7, 9, 10), 
           extra_css = "border-bottom: hidden") 
table

The above code gave me a nice table. (Unfortunately, I do not seem to be able to post it because I have not earned enough reputation.)

(3) What I want to know

In the above, I manually typed in the F statistics, stars, and p-values in rows to obtain the table I wanted, but I would like to find out if there is a way to extract information from F3 and F6 and import it to the table.

Upvotes: 2

Views: 816

Answers (2)

Vincent
Vincent

Reputation: 17853

If I understand correctly, you want to:

  1. Add two rows to the bottom of the table: F statistic and associated p-value
  2. These rows should be added only to some models, which you pick manually

The simplest way to achieve this is to use the add_rows argument you use in your example. Your approach is correct!

If you want a more general and automated strategy, you can define a glance_custom.lm_robust method.

Your example was complicated, so I took the liberty of simplifying it to turn it into a Minimal Reproducible Example. You will notice that I create and check a new attribute to determine which models will have a linear hypothesis test in the table.

(Note: answering your question led me to discover a minor bug which mixed the order of rows at the bottom of the table. This bug is now fixed. The table pasted below was produced using the development version of modelsummary 0.9.2.9000, which you can install by calling: remotes::install_github("vincentarelbundock/modelsummary") )

library(modelsummary)
library(estimatr)
library(tibble)
library(car)

mod1 <- lm_robust(mpg ~ am + vs, mtcars)
mod2 <- lm_robust(mpg ~ am + vs + hp, mtcars)
mod3 <- lm_robust(mpg ~ am + vs + wt, mtcars)
mod4 <- lm_robust(mpg ~ am + vs + qsec, mtcars)

# models 2 and 4 will have a linear hypothesis test
attr(mod2, "FTEST") <- TRUE
attr(mod4, "FTEST") <- TRUE

glance_custom.lm_robust <- function(x) {
  # check if we should include the linear hypothesis test in this specific model
  if (!isTRUE(attr(x, "FTEST"))) return(NULL)

  # conduct linear hypothesis test
  ftest <- linearHypothesis(x, test = "F", c("am = 0", "vs = 0"))

  # return a 1-row tibble with each statistic in separate columns
  out <- tibble(
    "$H_0: \\beta_{\\rm{vs}} = 0, \\beta_{\\rm{am}} = 0$" = ftest[["F"]][2],
    "     " = sprintf("(%.3f)", ftest[["Pr(>F)"]][2]))
  return(out)
}

modelsummary(list(mod1, mod2, mod3, mod4), escape = FALSE)

enter image description here

Upvotes: 2

Bloxx
Bloxx

Reputation: 1560

If I understand correctly, you would like to export data from the model. Just call it out:

F3$F

and

F3$`Pr(>F)`

Upvotes: 0

Related Questions