Formatting notes in R's stargazer tables
stargazer returns its output invisibly as a character vector, specifically so you can post-process it. Depending what you want to change, this may involve some regex. Or, as in this case, if you know what your notes line should look like, you can simply replace the wrong line with what you want. Here's a minimal reproducible example:
df <- data.frame(x = 1:10 + rnorm(100),
y = 1:10 + rnorm(100))
reg <- lm(y ~ x, data = df)
star <- stargazer(reg,
style = "qje", notes.append = FALSE, notes.align = "l",
notes = "This will be replaced")
note.latex <- "\\multicolumn{5}{l} {\\parbox[t]{11cm}{ \\textit{Notes:} Logistic regression. Dependent variable: an indicator varible ... AND Some very long and interesting comment.}} \\\\"
star[grepl("Note",star)] <- note.latex
cat (star, sep = "\n")
Including notes on stargazer table distorts distance between columns
LaTeX solution
I had a similar issue, and here's my solution for LaTeX.
First, you need a separate function that creates its own minipage where the note is included.
library(stargazer)
stargazernote <- function(starGazerCmd, outputfile, note){
# inserts 'note' to the end of stargazer generated latex table
ssn <- gsub(x=starGazerCmd, pattern='\\end{tabular}',
replacement=paste('\\end{tabular}', '\n',
'\\centerline{\\begin{minipage}{0.95\\textwidth}~\\', '\n',
'\\footnotesize{' , note,
'} \\end{minipage}}', sep=''), fixed=T)
cat(ssn,sep='\n',file=outputfile)
}
(You might want to play around with the parameter {0.95\\textwidth}
. Some people like slightly wider or narrower width for their notes.)
Create your stargazer latex table without the note as follows:
s <- stargazer(data,
type = "latex",
style = "AER",
notes.append=FALSE,
)
Then create the note separately:
note <- "All models were estimated by fixed effects estimator. Errors are robust to heteroscedasticity and autocovariance. Numbers between parenthesis are the coefficient standard deviations. * represents significance at the 10 \\% level, ** represents significance at the 5\\% level, and *** represents significance at the 1\\% level. Models (1), (2) and (3) refer, respectively, to equations (7), (8) and (9)"
Here's a first gotcha: the %
sign is interpreted as a comment symbol by LaTeX, so you need to escape your %
's by prepending them with \\
.
Now you can use the function above to collate the note and the LaTeX table:
stargazernote(s, note=note, outputfile='foo.tex')
The output looks like this:
The second gotcha is that you need to remember to include graphicx in your LaTeX file. Here's what a .tex file might look like:
\documentclass[english]{article}
\usepackage[T1]{fontenc}
\usepackage[latin9]{inputenc}
\usepackage{graphicx} %% note: the table will not render without this package.
\begin{document}
\include{foo.tex}
\end{document}
Text solution
You can force line changes in notes like this (this is copied from this SO question):
stargazer(data,
type = "text",
notes= c("All models were estimated by fixed effects estimator.",
"Errors are robust to heteroscedasticity and autocovariance.",
"Numbers between parenthesis are the coefficient standard deviations.",
"* represents significance at the 10 % level",
"** represents significance at the 5% level,",
"and *** represents significance at the 1% level.",
"Models (1), (2) and (3) refer, respectively, to equations (7), (8) and (9)"),
style = "AER")
Output:
=================================================================================
Statistic N Mean St. Dev. Min Pctl(25) Pctl(75) Max
---------------------------------------------------------------------------------
V1 7 0.184 0.380 -0.230 -0.004 0.231 0.957
V2 7 -0.083 1.018 -1.246 -0.827 0.631 1.322
V3 7 -0.058 0.752 -0.733 -0.610 0.495 1.025
V4 7 -0.316 1.106 -2.223 -0.725 0.412 1.120
V5 7 -0.242 0.927 -1.777 -0.809 0.397 0.743
V6 7 -0.020 1.403 -1.453 -1.202 0.756 2.348
V7 7 0.565 1.130 -1.459 0.156 1.224 2.023
V8 7 0.840 0.938 -0.493 0.334 1.302 2.256
V9 7 -0.191 0.761 -1.012 -0.766 0.236 1.107
V10 7 0.530 0.643 -0.222 0.144 0.680 1.768
V11 7 0.263 0.396 -0.230 -0.004 0.432 0.957
---------------------------------------------------------------------------------
All models were estimated by fixed effects estimator.
Errors are robust to heteroscedasticity and autocovariance.
Numbers between parenthesis are the coefficient standard deviations.
* represents significance at the 10 % level
** represents significance at the 5% level,
and *** represents significance at the 1% level.
Models (1), (2) and (3) refer, respectively, to equations (7), (8) and (9)
Add a row with notes using stargazer
stargazer(linear.1, linear.2, type="text", keep.stat=c("n"),
add.lines=list(c("Note 1", "X", ""), c("Note 2", "", "X")))
Does the trick.
Stargazer column on multiple lines *with multiple models*?
Ok, my apologies, I was really close, I should have looked a little harder before posting. The key was 1) to use \shortstack
instead of \mbox
and 2) not to escape the {
characters.
var1<-rnorm(100)
var2<-rnorm(100)
df<-data.frame(var1, var2)
mod<-lm(var1~var2)
library(stargazer)
stargazer(mod, mod, column.labels=c('\\shortstack{my models \\\\ need long titles}',
'\\shortstack{my models \\\\ need long titles}'))
Getting Stargazer Column labels to print on two or three lines?
One option: You can insert latex codes for newline (\\
) and table column alignment (&
). Note that each \
needs to be "escaped" in R with another \
.
stargazer(mod, column.labels='my models\\\\ & need long titles')
Another way is to multirow. This could be easier for more complex tables with different length headings on each column. You will need to add \usepackage{multirow}
to your document preamble.
stargazer(mod, column.labels='\\multirow{2}{4 cm}{my models need long titles}')
You will also need to post-edit the latex output from stargazer to insert some extra lines (using \\
) below the variable headings so that the rest of the table gets moved down also (as in the exceprt below):
& \multirow{2}{4 cm}{my models need long titles} \\
\\ % note the extra line inserted here before the horizontal rule
\hline \\[-1.8ex]
Add line with datasets at top of table (stargazer R package)
In the stargazer()
function, the row you refer to is governed by the dep.var.caption
option. Unfortunately, since you want more than one column in this row, you can't accomplish what you want without some tinkering; if you pass a vector of length > 1 to this option, stargazer()
will throw an error. So, we'll have to make a custom function that captures the output from stargazer()
and modifies it accordingly before printing it.
The following .Rmd file worked fine for me (output below the code):
---
title: "Stack Overflow Answer"
author: "duckmayr"
date: "November 3, 2017"
output: pdf_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
```{r, echo=FALSE}
custom_table <- function(dataset_labels, ...) {
tbl <- capture.output(stargazer::stargazer(...))
pattern1 <- 'Dependent variable:'
pattern2 <- '(?<= \\& ).+(?= \\\\)'
first_row_index <- which(grepl(pattern=pattern1, x=tbl))
first_row <- tbl[first_row_index]
colspan <- as.numeric(gsub(pattern='[^0-9]+', replacement='', first_row))
colspan <- colspan / length(dataset_labels)
new_first_row <- sub('[0-9]+', colspan, first_row)
replacement <- rep(stringr::str_extract(new_first_row, pattern2), 2)
replacement <- stringr::str_replace(replacement, pattern1, dataset_labels)
replacement <- paste(replacement, collapse=' & ')
new_first_row <- stringr::str_replace(new_first_row, pattern2, replacement)
new_first_row <- stringr::str_replace_all(new_first_row, 'multi', '\\\\multi')
new_first_row <- stringr::str_replace_all(new_first_row, 'textit', '\\\\textit')
tbl[first_row_index] <- new_first_row
cat(tbl, sep='\n')
}
swiss2 <- swiss[1:20,]
m1 <- lm(Fertility ~ Agriculture, data = swiss)
m2 <- lm(Fertility ~ Examination, data = swiss)
m3 <- lm(Infant.Mortality ~ Education, data = swiss)
m4 <- lm(Infant.Mortality ~ Catholic, data = swiss)
m5 <- lm(Fertility ~ Agriculture, data = swiss2)
m6 <- lm(Fertility ~ Examination, data = swiss2)
m7 <- lm(Infant.Mortality ~ Education, data = swiss2)
m8 <- lm(Infant.Mortality ~ Catholic, data = swiss2)
```
```{r, echo=FALSE, results='asis'}
custom_table(c('Data: Swiss', 'Data: Swiss2'),
m1, m2, m3, m4, m5, m6, m7, m8,
type = "latex",
header=FALSE,
omit.stat=c("LL","ser","f","adj.rsq"),
font.size="tiny",
column.labels = c("(M1)", "(M2)", "(M3)", "(M4)", "(M5)", "(M6)", "(M7)", "(M8)"),
model.names = FALSE,
model.numbers = FALSE,
star.cutoffs = c(0.05, 0.01, 0.001),
dep.var.labels = c("Outcome 1", "Outcome 2", "Outcome 1", "Outcome 2"))
```
EDIT:
If you'd prefer the output to go to a tex file rather than (or in addition to) directly using the output in the .Rmd file, we can make the following tweak:
custom_table <- function(dataset_labels, ..., cat_output=TRUE, out_file=NULL) {
tbl <- capture.output(stargazer::stargazer(...))
pattern1 <- 'Dependent variable:'
pattern2 <- '(?<= \\& ).+(?= \\\\)'
first_row_index <- which(grepl(pattern=pattern1, x=tbl))
first_row <- tbl[first_row_index]
colspan <- as.numeric(gsub(pattern='[^0-9]+', replacement='', first_row))
colspan <- colspan / length(dataset_labels)
new_first_row <- sub('[0-9]+', colspan, first_row)
replacement <- rep(stringr::str_extract(new_first_row, pattern2), 2)
replacement <- stringr::str_replace(replacement, pattern1, dataset_labels)
replacement <- paste(replacement, collapse=' & ')
new_first_row <- stringr::str_replace(new_first_row, pattern2, replacement)
new_first_row <- stringr::str_replace_all(new_first_row, 'multi', '\\\\multi')
new_first_row <- stringr::str_replace_all(new_first_row, 'textit', '\\\\textit')
tbl[first_row_index] <- new_first_row
if ( cat_output ) {
cat(tbl, sep='\n')
}
if ( !is.null(out_file) ) {
cat(tbl, sep='\n', file=out_file)
}
}
Then if you run the code below in an R script, or put it in a chunk in an Rmd file, you will get the output written to the file 'test_out.tex' as well as directly output:
custom_table(c('Data: Swiss', 'Data: Swiss2'),
out_file='test_out.tex',
m1, m2, m3, m4, m5, m6, m7, m8,
type = "latex",
header=FALSE,
omit.stat=c("LL","ser","f","adj.rsq"),
font.size="tiny",
column.labels = c("(M1)", "(M2)", "(M3)", "(M4)", "(M5)", "(M6)", "(M7)", "(M8)"),
model.names = FALSE,
model.numbers = FALSE,
star.cutoffs = c(0.05, 0.01, 0.001),
dep.var.labels = c("Outcome 1", "Outcome 2", "Outcome 1", "Outcome 2"))
Using the out
option of the stargazer()
function won't quite work because stargazer()
will write the output to out
before we've had a chance to make our modifications to it, but this tweak works.
Related Topics
How to Get All Possible Combinations of N Number of Data Set
How to Install The Fftw3 Package of R in Ubuntu 12.04
Combine (Bind) Existing PDF Files in R
Remove Whiskers in Box-Whisker-Plot
How to Use Custom Cross Validation Folds with Xgboost
"Nas Introduced by Coercion" During Cluster Analysis in R
Extract Names of Deeply Nested Lists
Reconstruct Symmetric Matrix from Values in Long-Form
Coloring a Geom_Histogram by Gradient
Why Ggplot2 Legend Not Show in The Graph
Calculate a 2D Spline Curve in R
How to Change The Character Encoding of .R File in Rstudio
Optimization of a Function in R ( L-Bfgs-B Needs Finite Values of 'Fn')
How to Remove Rows with Nas Only If They Are Present in More Than Certain Percentage of Columns