# Generating regression tables in R

I often need to document the statistical results I estimate in table format. I have tried many, many things over the years, and none of my solutions are perfect, including the one I’m about to describe. But, it is now… pretty good.

First, I define a function that takes a list of fitted models (`models`

) and some other variables and outputs a list of pieces that I can create a table with. See below for the function definition.

```
library(stargazer)
#' @param models A list of fitted models that stargazer can process
#' @param keep Length 1 character vector of variables to display in table
#' @param covariate.labels Labels for keep
#' @param digits Number of digits to use for numbers in the table
#'
#' @return List of pieces of a tabular with named items header, inner, and footer
make_tex_pieces <- function(models, keep, covariate.labels, digits = 2) {
# models: a
# Use stargazer, but keep as little extra stuff as possible
tex_raw <- stargazer(models,
keep = keep, covariate.labels = covariate.labels,
digits = digits,
table.layout = "t", no.space = T, align = T)
# Split up into header, footer, and inner
idx0 <- grep("begin{tabular}", tex_raw, fixed = T) # Start of \begin{tabular}
idx1 <- grep("end{tabular}", tex_raw, fixed = T) # End of \begin{tabular}
tex_header <- c(tex_raw[idx0], "\\toprule")
tex_footer <- c("\\bottomrule", tex_raw[idx1])
# Remove [-1.8ex] and get the inside of the tabular
tex_inner <- gsub("\\\\[-[\\.0-9]+ex]", "", tex_raw[(idx0+1):(idx1-1)])
# Return these as a 3 element list so that the user can insert header rows (column labels)
# and footer rows (summary statistics, fixed effects)
list(header = tex_header, inner = tex_inner, footer = tex_footer)
}
```

Once I have that function defined, I can use it to create the inside part of the table: the `tabular`

command.

```
# Load a sample dataset and run regression
data(cars)
fit <- lm(speed ~ dist, data = cars)
# Use the function we defined above to split the regression output into different pieces of a tabulr
pieces <- make_tex_pieces(fit, "dist", "distance")
```

% Table created by stargazer v.5.2.2 by Marek Hlavac, Harvard University. E-mail: hlavac at fas.harvard.edu
% Date and time: Sat, Mar 13, 2021 - 16:52:54
% Requires LaTeX packages: dcolumn
```
# Put the pieces back together, adding a short panel with the count of observations
latex_output <- c(pieces$header,
pieces$inner,
"\\midrule",
sprintf("Observations & %.0f \\\\", length(fit$model$dist)),
pieces$footer)
# Write to file (I leave commented)
# write(latex_output, "model-tabular.tex")
latex_output
```

[1] “\begin{tabular}{@{\extracolsep{5pt}}lD{.}{.}{-2} }”
[2] “\toprule”

[3] " distance & 0.17^{***} \\ "

[4] " & (0.02) \\ "

[5] “\midrule”

[6] “Observations & 50 \\”

[7] “\bottomrule”

[8] " \end{tabular} "

Next, I use the LaTeX `threeparttable`

package (also used in this post) to display the table. Here’s a minimum example.

```
\documentclass{article}
\usepackage{booktabs} % Nice-looking tables
\usepackage{dcolumn} % Booktabs column spacing
\usepackage{threeparttable} % Align column caption, table, and notes
% Flexible notes environment based on minipage
\newenvironment{notes}[1][Notes]{\begin{minipage}[t]{\linewidth}\normalsize{\itshape#1: }}{\end{minipage}}
\begin{document}
\begin{table}
\centering
\begin{threeparttable}
\caption{My table}
\input{model-tabular.tex}
\begin{notes}
* p $<$ 0.1, ** p $<$ 0.05, *** p $<$ 0.01. This regression is not confounded at all.
\end{notes}
\end{threeparttable}
\end{table}
\end{document}
```

And here’s the result.

Other packages you might find useful:

- huxtable is a good solution for generating
*quick*regression tables for export to Markdown or HTML. I find its LaTeX output functions fairly cumbersome. - kable/kableExtra are great for general purpose table creation, but can’t easily process fitted model output.