`etable` in `fixest` package — how to make an AER-like paper regression table in R

Common Used package in R

  1. xtable: plain tex
  2. kableExtra: dataframe as tex table
  3. fixest: further with frequent latex options

Concept of fixest

  1. fixest provides sw (stepwise) and csw (cumulative stepwise) function for regression formula
    -> Pros: do not need to write regressions in separate lines
    -> Cons: convenient for nested models, not for general purposes
  2. use feols (fixed effect OLS) to estimate regression models (create fixest model objects)
    We can still make one model one regression as we wish to.
  3. use etable (estimation table) to export regression output into dataframe or tex format.

Example

est1 <- feols(sw(prc, LNprc_hh, prc_banks, prc_inve, prc_insu, prc_mut, prc_pens) ~ be_s + ebit_s | fdate, # fixed effect: fdate 
data=main_data, cluster = ~fdate) # cluster se by fdate
etable(est1,
tex = TRUE,
postprocess.tex = setLineWidth, linewidth = TRUE,
style.tex = style.tex(main = "aer", # main style
line.top = "\\midrule", # single line or double lines
line.bottom = "\\midrule", # on the top or the bottom
var.title = "\\midrule", # default is "\midrule \emph{Variables}"
model.title = "", # default is "Model:"
depvar.title = "Dependent Variable:", #
fixef.title = "\\midrule", # Since we only have one fixed effect to note, we add a separate line here
yesNo = c("Quarter", "No"), # cells to display in the fixed effect
fixef.prefix = "", #
fixef.suffix = "", #
fixef.where = "var", # "var" after the variables; "stats" after R^2
# tablefoot = TRUE,
# tablefoot.value = footnote,
tabular = "X" # use tabular* or tabularx if X
),

style.df = style.df(depvar.title = "Dependent Variable: ",
yesNo = c("Quarter", "No"),
fixef.prefix = "",
fixef.suffix = "",
))

We want to estimate 7 regression models, and the only difference is the dependent variable.

  • The vertical bar inside the formula indicates the fixed effect indicator.
  • style.tex controls the output when tex = T, and style.dfcontrols the output when tex = F

Postprocess tex

  • postprocess.tex can handle the plain tex output (only when tex = T) with a self-defined function. For example, if I want the output table to have linewidth option instead of textwidth, I can simply define a function below to override the original table width option.
# change the `\textwidth` argument into `\linewidth` in LaTeX
# to better adjust the table width with tabularx environment
setLineWidth <- function(x, linewidth = TRUE) {
# x is the char vector returned by etable
if (linewidth) {
# change \begin{tabularx}{\textwidth}{xXXXXXXX}
x <- stringr::str_replace(x, ("textwidth"), ("linewidth"))
# make the first column l
x <- stringr::str_replace(x, "XXXXXXXX", "lXXXXXXX")
}
return(x)
}

Variable Naming Dictionary

variable naming is always a hassle when outputting tables. Thanks to fixest and its clever design, we can easily set up a variable naming mapping with setFixest_dict

# Setting a dictionary 
keyvalues <- c(prc = "PRC",
LNprc_hh = "Households",
prc_banks = "Banks",
prc_inve = "Investment company",
prc_insu = "Insurance company",
prc_mut = "Mutual funds",
prc_pens = "Pension funds",
be_s = "Book
equity",
ebit_s = "OP" ,
beta = "\\beta",
fdate = "Fixed \\\ Effect"
)
setFixest_dict(keyvalues)

Number of digits

We can restrict the output to always display 4 digits

# make the table alawys display four digits
setFixest_etable(digits = "r4", digits.stats = "r4")

See this github issue for more information.
https://github.com/lrberge/fixest/issues/82

Output after rendered from tex

Then we have the following table

Integrate with RSweave (.Rnw files)

Below are the pseudo-codes for integrating the fixest outputs and RSweave.

<<setup, echo = FALSE, results= 'hide', message = FALSE, warning = FALSE, include=FALSE>>=library(fixest) # used for fixed effect estimation and exporting tablesdata <- load(...)
@
% Below are latex codes
\Sexpr{ifelse(is_tab_landscape, beg_landscape_str, "")}
\begin{table}[h]\begin{adjustwidth}{-48pt}{-48pt}\singlespacing
\footnotesize
\Sexpr{shift_table_vspace}\caption{\small \Sexpr{tab_title}}
\label{\Sexpr{tab_label}}
{\noindent
\Sexpr{tab_topline}
}
\centering\bigspace<<tab, echo = FALSE, results = 'asis', message = FALSE, warning = FALSE>>=# Create tables with fixest::etable()# Setting a dictionary
keyvalues <- c(y = "wage",
educ = "education",
fss = "family social status",
state = "residental state",
year = "year recorded"
)
setFixest_dict(keyvalues)
# make the table alawys display four digits
setFixest_etable(digits = "r4", digits.stats = "r4")
# change the `\textwidth` argument into `\linewidth` in LaTeX
# to better adjust the table width with tabularx environment
setLineWidth <- function(x, linewidth = TRUE) {
# x is the char vector returned by etable
if (linewidth) {
# change \begin{tabularx}{\textwidth}{xXXXXXXX}
x <- stringr::str_replace(x, ("textwidth"), ("linewidth"))
# make the first column l
x <- stringr::str_replace(x, "XXXXXXXX", "lXXXXXXX")
}
return(x)
}
est1 <- feols(y ~ educ + fss | csw0(state, year), # fixed effect: fdate
data = data, cluster = ~state) # cluster se by fdate
etable(est1,
tex = TRUE,
postprocess.tex = setLineWidth, linewidth = TRUE,
style.tex = style.tex(main = "aer",
var.title = "\\midrule",
depvar.title = "Dependent Variable:",
yesNo = c("Yes", "No"),
tabular = "X"
),
style.df = style.df(depvar.title = "Dependent Variable: ",
yesNo = c("Yes", "No"),
fixef.prefix = "",
fixef.suffix = "",
))
@\end{adjustwidth}\end{table}\Sexpr{ifelse(is_tab_landscape, end_landscape_str, "")}

Reference

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store