0

I was wondering how to use modelsummary to combine model names and DV names as in outreg2 in Stata? Here is the reprex:

    url <- 'https://vincentarelbundock.github.io/Rdatasets/csv/HistData/Guerry.csv'
dat <- read.csv(url)
models <- list(
  "OLS 1"     = lm(Donations ~ Literacy + Clergy, data = dat),
  "Poisson 1" = glm(Donations ~ Literacy + Commerce, family = poisson, data = dat),
  "OLS 2"     = lm(Crime_pers ~ Literacy + Clergy, data = dat),
  "Poisson 2" = glm(Crime_pers ~ Literacy + Commerce, family = poisson, data = dat),
  "OLS 3"     = lm(Crime_prop ~ Literacy + Clergy, data = dat)
)
modelsummary(models)

#N: DV names
modelsummary(dvnames(models), output = "flextable", estimate="{estimate}{stars}",
             statistic = 'statistic', stars = c('*' = .1, '**' = .05, '***'=0.01))
#N: Model names
modelsummary(models, output = "flextable", estimate="{estimate}{stars}",
             statistic = 'statistic', stars = c('*' = .1, '**' = .05, '***'=0.01))

Here is how a DV and model name combined table would look in outreg2 in Stata: enter image description here

Any info or advice would be appreciated!

  • If you want to add a distinct row with dependent variables, you might want to use the `add_rows` argument: https://vincentarelbundock.github.io/modelsummary/articles/modelsummary.html#add-rows – Vincent Dec 17 '21 at 20:42
  • Hi @Vincent, I looked at add_rows. Is there any way to dynamically extract the dep variables and build the rows tribble on the fly so that we don't have prespecify the terms in advacne? Is that the only way? – astrae_research Dec 17 '21 at 23:24
  • I'm using add_rows just to change the terms using the following adaptation of your code: `library(tibble) rows <- tribble(~term, ~OLS, ~Logit) attr(rows, 'position') <- c(0) modelsummary(models, add_rows = rows)` But it throws an error: Assertion on 'add_rows' failed: Must have at least 1 rows, but has 0 rows. – astrae_research Dec 17 '21 at 23:39

1 Answers1

1

You could use the add_rows argument and create your own custom function to automate the process:

library(modelsummary)

insert_row <- function(x) {
    out <- c("DV:", names(dvnames(x)))
    out <- data.frame(as.list(out))
    attr(out, "position") <- 0
    return(out)
}

mod <- list(
    lm(mpg ~ hp, mtcars),
    lm(vs ~ hp, mtcars))

modelsummary(mod, add_rows = insert_row(mod))
Model 1 Model 2
DV: mpg vs
(Intercept) 30.099 1.217
(1.634) (0.150)
hp -0.068 -0.005
(0.010) (0.001)
Num.Obs. 32 32
R2 0.602 0.523
R2 Adj. 0.589 0.507
AIC 181.2 28.3
BIC 185.6 32.7
Log.Lik. -87.619 -11.134
F 45.460 32.876
Vincent
  • 15,809
  • 7
  • 37
  • 39
  • 1
    Works great and also gives some help on how to add features to the package! Thank you! – astrae_research Dec 22 '21 at 09:22
  • Not sure if I should open a new question, but is there a way to stipulate the row position programmatically? Say the last row of whatever size the table will be or the row before R2? Again, thank you for your answers - most helpful! – astrae_research Jan 13 '22 at 06:21
  • Yes. My code above shows how to set the "position". You will also find a description in the documentation of `add_rows` ( type `?modelsummary`) and on the website: https://vincentarelbundock.github.io/modelsummary/articles/modelsummary.html#add_rows – Vincent Jan 13 '22 at 13:59
  • I went over that info several times and the only example is when position is a predetermined constant "attr(rows, 'position') <- c(3, 9)". Is there a way to make it dynamic? Sort of like "attr(rows, 'position') <- c(3, nrow(future_reg_coefficient_table))"? Whatever the number of rows in the resulting table that particular row would always be appended as the bottom row. An even better approach could be just to specify "attr(rows, 'position') <- c(3, find(R2)-1)" where the row would be inserted right above a row with R2 in it. – astrae_research Jan 13 '22 at 21:54
  • Interesting idea, but it would be hard to implement. A workaround would be to generate the table twice. The first time you `output="data.frame"`, then you dynamically figure out where to insert it in the data frame, and you use that info to prep your `add_rows`. Not ideal, but shouldn't take more than 3-4 lines of code. – Vincent Jan 14 '22 at 00:29