Search code examples
rlatexr-markdownlinear-regressionstargazer

How Can We Display F-Statistic / Degrees of Freedom in two lines


I am using Stargazer to output a regression table with multiple lm models together. The problem is that Stargazer outputs the F-Statistic and degrees of freedom in a single line by default. If you have 3 or 4 models, that means the output in latex is unnecessarily wide and extends past the page.

There is an option to hide the degrees of freedom using:

stargazer(lm1,lm2,lm3,lm4, df = F)

But, there is no way to get it to display on two rows.

Here's a reproducible example of the bad outcome:

lm.out.1 <- lm(stack.loss ~ Air.Flow , data=stackloss)
lm.out.2 <- lm(stack.loss ~ Water.Temp, data=stackloss)
lm.out.3 <- lm(stack.loss ~ Acid.Conc., data=stackloss)
lm.out.4 <- lm(stack.loss ~ Air.Flow + Water.Temp, data=stackloss)
lm.out.5 <- lm(stack.loss ~ Air.Flow + Water.Temp + Acid.Conc., data=stackloss)

stargazer(lm.out.1, 
          lm.out.2,
          lm.out.3,
          lm.out.4,
          lm.out.5)

When you render the latex output, you get an unnecessarily wide table: enter image description here

Which is outside the margins when your render to print: enter image description here

It is possible to see how this table could be neatly and efficiently rendered in a printable manner using the df=F option:

stargazer(lm.out.1, 
          lm.out.2,
          lm.out.3,
          lm.out.4,
          lm.out.5, df = F)

Which produces the following: enter image description here

BUT, now we have lost the information about the degrees of freedom.

Is there any way to print that information with a line-break so that it prints on two rows of the table?

There seems to be something helpful posted by the package author here - about adding degrees of freedom: Displaying degrees of freedom in stargazer table

I am not sure how to take that and get the desired output of F-Stat and DF on two lines...


Solution

  • You have to hack the output of stargazer() to make a table that displays F-statistics and dfs in distinct lines. A user-defined function in this answer (show_F_in_two_lines()) will produce a table as shown below.

    enter image description here

    library(stringr)
    
    show_F_in_two_lines <- function(stargazer) {
      # `Stringr` works better than base's regex 
      require(stringr)
    
      # If you remove `capture.output()`, not only the modified LaTeX code 
      # but also the original code would show up
      stargazer <- stargazer |>
        capture.output()
    
      # Reuse the index in which F-statistics are displayed
      position_F <- str_which(stargazer, "F Statistic")
    
      # Extract only F-statistics
      Fs <- stargazer[position_F] |>
        str_replace_all("\\(.*?\\)", "")
    
      # Extract only df values and make a new line for them
      dfs <- stargazer[position_F] |>
        str_extract_all("\\(.*?\\)") |>
        unlist() |>
        (
          \(dfs)
          paste0(" & ", dfs, collapse = "")
        )() |>
        paste0(" \\\\")
    
      # Reuse table elements that are specified
      # after the index of F-statistics
      after_Fs <- stargazer[-seq_len(position_F)]
    
      c(
        stargazer[seq_len(position_F - 1)],
        Fs,
        dfs,
        after_Fs
      ) |>
        cat(sep = "\n")
    }
    
    stargazer(
      header = FALSE,
      lm.out.1,
      lm.out.2,
      lm.out.3,
      lm.out.4,
      lm.out.5
    ) |>
      show_F_in_two_lines()