Skip to content

Instantly share code, notes, and snippets.

@Oravishayrizi
Created December 4, 2022 09:35
Show Gist options
  • Save Oravishayrizi/1089a464184230902b5b85baa1e3454b to your computer and use it in GitHub Desktop.
Save Oravishayrizi/1089a464184230902b5b85baa1e3454b to your computer and use it in GitHub Desktop.
Latex table stuff

Hi,

I currently use the package fixest to estimate my regressions. Then, I use the etable function to produce a latex table with the results of multiple regressions.

I wrote a simple wrapper to make this pipeline a little bit smoother. Also, as other colleagues of mine use esttab command from stata, I wanted my table to have the same format, so we could easily interchange tables prodcued in r or stata.

The following gist is consisted of two parts.

  1. The R part: I added post process with the indicative name "mypostprocess", the postprocess has a few parts that one can shut down manually and independently:

mypostprocess

mypostprocess = function(x,onlyinner=TRUE,addfilename=TRUE ,comment_out_clutter=TRUE){
    if(comment_out_clutter){
        qui_se = grep("standard-errors in parentheses", x)
        qui_significance = grep("Signif. Codes", x)
        
        x[qui_se] = paste0("%",x[qui_se])
        x[qui_significance]= gsub("\n","\n%",x[qui_significance])
        
        class(x) = "etable_tex"
    }
    
    if(onlyinner){
        qui_start = grep("begin\\{tabular", x)
        qui_end = grep("end\\{tabular", x)
        x = (x[(qui_start+1):(qui_end-1)])
        class(x) = "etable_tex"
    }
    if(addfilename){
        current_path = rstudioapi::getActiveDocumentContext()$path 
        current_file = gsub(".*/","",current_path)
        x[length(x)+1] = paste0("% This table produced by the following file: \"",current_file,"\" on: ",Sys.Date()," \n ")
    }
    x
}

What's inside this postprocess?

A. comment_out_clutter

More often than not, I don't want to present the significane legend, nor how I cluster my Standart errors. I manually specify those details in the table's notes to save some space I comment out those lines instead of deleting them since I want to store the information. I simply don't want Latex to present it.

B. onlyinner

This argument deletes the \begin{tabular} and \end{tabular} I use it to replicate 'esttab' outputs.

C. addfilename

I really like this argument! It prints (as a comment) the file's name and the date of producing the table. I find that super useful when I want to update a table in my paper, without the need to find which file produces it. This argument requires 'rstudioapi' package.

An example of producng latex table using this postprocess

library(fixest)

df<-iris

lm1<-feols(Sepal.Length~Sepal.Width|Species,data=df)
lm2<-feols(Sepal.Length~Sepal.Width+Petal.Length|Species,data=df)
lm3<-feols(Petal.Length~Sepal.Width|Species,data=df)

etable(lm1,lm2,lm3,
       vcov="hetero", #For clustered Ste, use vcov = ~Species)
       digits = "r3",                         # rounding - coef/se
       digits.stats = "r2",                   # rounding - fit stat (R^2 etc)
       fitstat=c('r2','n'),                   # Which fit stat to keep?
       style.tex = style.tex("base",line.top = "",line.bottom = "",
                             model.title="",stats.title="",
                             fixef.title = "",slopes.title = "",
                             fixef.suffix = " FE",fixef.prefix = "%",
                             var.title = "\\midrule", yesNo = "$\\checkmark$"),
       headers = list("^:_:"=list("group1"=2,"group2"=1), 
                      "^:_:"=list("a","b","c")),
       extralines = list("^:_:"=list("group1"=2,"group2"=1), 
                         "^:_:"=list("a","b","c")),
       postprocess.tex = mypostprocess,
       # One of the following lines should be commented out.       
       onlyinner=FALSE,view=TRUE,                            # The trial and error phase #
       #replace = TRUE,file = "../tables/mynewtable.tex",    # Save the table
       tex = TRUE)

The view=True renders the table in Rstudio Viewer, so I don't have to save a table, copy it to overleaf, compile it, just to find out that this is not the table I wanted in terms of specification or styling. However, in order to use the view=TRUE I need to shut off the onlyinner part (using onlyinner=FALSE).

When everything is ready, I comment out the following line onlyinner=FALSE,view=TRUE,, and uncommenting this line #replace = TRUE,file = "../tables/mynewtable.tex",

  1. The latex part the latex part is mainly based on the functions from this url - https://www.jwe.cc/2012/08/latex-stata-design/

Specifically, I add this lines of code to the preamble.

\makeatletter %this is needed to allow latex to revert to prior installations to fix noalign error 
\let\estinput=\@@input %define a new input command so that we can still flatten the document 

\newcommand{\estwide}[4]{
	\vspace{.75ex}{
		\begin{tabular*}
			{#1}{@{\hskip\tabcolsep\extracolsep\fill}l*{#3}{#4}}
			\toprule
			\toprule
			\estinput{#2}
			\bottomrule
			\bottomrule
			\addlinespace[.75ex]
    		\end{tabular*}
	}
}	

% Table\Figures notes
\newcommand{\signifnote}{* p < 0.1, ** p < 0.05, *** p < 0.01.}
\newcommand{\clusternote}[1]{Standard errors are clustered at the #1 level and reported in parentheses. \signifnote}

\newenvironment{tablenotes}[1][1\linewidth]{\begin{minipage}[t]{ #1}\small{\itshape{Notes}: }}{\end{minipage}}

In the main text, I add the following:

\begin{table} 
\centering
\caption{A beautiful table}\label{tab:wow} 
	\estwide{0.8\textwidth}{Tables/mynewtable}{3}{c}
    \begin{tablenotes}[0.8\textwidth]
	 All regressions include Spices FE. Heteroskedasticity-robust standard-errors in parentheses. \signifnote}
	\end{tablenotes}
\end{table}

When standard errors of all the regressions are clustered in the same way, adding \clusternote{state} will add the following comment to the notes:

Standard errors are clustered at the state level and reported in parentheses. * p < 0.1, ** p < 0.05, *** p < 0.01.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment