Objectives:


Math Notation

There are three ways to set up math notation:

\[ Y_i = \hat{\alpha} + \hat \beta X_i + \varepsilon_i \]

For example:

\begin{align*}
H_0 &: \beta_1 = 0 \\
H_A &: \beta_1 \neq 0
\end{align*}

You can mix regular text and math in R Markdown. This is very useful when you are explaining your models and hypotheses.


Presenting Regression Results with stargazer

Load the package via:

library(stargazer)
## 
## Please cite as:
##  Hlavac, Marek (2022). stargazer: Well-Formatted Regression and Summary Statistics Tables.
##  R package version 5.2.3. https://CRAN.R-project.org/package=stargazer

We will use the iris dataset for illustration.

data(iris)
iris <- iris %>%
  filter(Species != "setosa") %>%
  mutate(Species = ifelse(Species == "virginica", 1, 0))

head(iris)
##   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1          7.0         3.2          4.7         1.4       0
## 2          6.4         3.2          4.5         1.5       0
## 3          6.9         3.1          4.9         1.5       0
## 4          5.5         2.3          4.0         1.3       0
## 5          6.5         2.8          4.6         1.5       0
## 6          5.7         2.8          4.5         1.3       0

We can compute regression results:

fit1 <- lm(Sepal.Length ~ Sepal.Width + Species, data = iris)
fit1
## 
## Call:
## lm(formula = Sepal.Length ~ Sepal.Width + Species, data = iris)
## 
## Coefficients:
## (Intercept)  Sepal.Width      Species  
##      3.4879       0.8838       0.4717

And use stargazer to produce a nicely formatted regression table:

stargazer(fit1,
          type = "text",  # Try: "latex" and "html"
          title = "Regression Results",
          dep.var.labels = c("Sepal Length"),
          covariate.labels = c("Sepal Width", "Virginica", "Intercept"),
          digits = 3,
          out.header = FALSE
          )
## 
## Regression Results
## ===============================================
##                         Dependent variable:    
##                     ---------------------------
##                            Sepal Length        
## -----------------------------------------------
## Sepal Width                  0.884***          
##                               (0.162)          
##                                                
## Virginica                    0.472***          
##                               (0.107)          
##                                                
## Intercept                    3.488***          
##                               (0.453)          
##                                                
## -----------------------------------------------
## Observations                    100            
## R2                             0.423           
## Adjusted R2                    0.411           
## Residual Std. Error       0.509 (df = 97)      
## F Statistic           35.484*** (df = 2; 97)   
## ===============================================
## Note:               *p<0.1; **p<0.05; ***p<0.01

Interpreting the Regression

In LaTeX notation, our model is:

\[ \text{SepalLength}_i = \hat\alpha + \hat{\beta}_1 \text{SepalWidth}_i + \hat{\beta}_2 \text{Virginica}_i + \hat{\varepsilon}_i \]


Multiple Models in One Table

stargazer can show more than one model at a time. This is useful when you want to compare specifications.

# set results = 'asis' in chunk options

fit2 <- lm(Sepal.Length ~ Sepal.Width + Petal.Length + Species, data = iris)
fit3 <- lm(Sepal.Length ~ Sepal.Width + Species + Sepal.Width * Species, data = iris)  # interaction

stargazer(fit1, fit2, fit3,
          type = "text",
          title = "Sepal Length: Model Comparison",
          dep.var.labels = c("Sepal Length"),
          column.labels = c("Baseline", "Add Petal Length", "Interaction"),
          covariate.labels = c("Sepal Width",
                               "Petal Length",
                               "Virginica",
                               "Sepal Width : Virginica",
                               "Intercept"),
          digits = 3,
          align = TRUE,
          no.space = FALSE
          )
## 
## Sepal Length: Model Comparison
## =============================================================================================
##                                                  Dependent variable:                         
##                         ---------------------------------------------------------------------
##                                                     Sepal Length                             
##                                Baseline           Add Petal Length          Interaction      
##                                  (1)                     (2)                    (3)          
## ---------------------------------------------------------------------------------------------
## Sepal Width                    0.884***                0.231*                 0.865***       
##                                (0.162)                 (0.119)                (0.233)        
##                                                                                              
## Petal Length                                          0.858***                               
##                                                        (0.074)                               
##                                                                                              
## Virginica                      0.472***               -0.503***                0.367         
##                                (0.107)                 (0.109)                (0.938)        
##                                                                                              
## Sepal Width : Virginica                                                        0.036         
##                                                                               (0.325)        
##                                                                                              
## Intercept                      3.488***               1.642***                3.540***       
##                                (0.453)                 (0.333)                (0.649)        
##                                                                                              
## ---------------------------------------------------------------------------------------------
## Observations                     100                     100                    100          
## R2                              0.423                   0.761                  0.423         
## Adjusted R2                     0.411                   0.753                  0.405         
## Residual Std. Error        0.509 (df = 97)         0.329 (df = 96)        0.511 (df = 96)    
## F Statistic             35.484*** (df = 2; 97) 101.704*** (df = 3; 96) 23.419*** (df = 3; 96)
## =============================================================================================
## Note:                                                             *p<0.1; **p<0.05; ***p<0.01

Note:


Adding Notes and Custom Lines

It is often helpful to add notes below your table:

stargazer(fit1, fit2,
          type = "html",
          title = "Sepal Length: Alternative Specifications",
          dep.var.labels = "Sepal Length",
          column.labels = c("Baseline", "Add Petal Length"),
          covariate.labels = c("Sepal Width", 
                               "Virginica",
                               "Petal Length"),
          digits = 3,
          add.lines = list(
            c("Controls", "No", "Yes")
          ),
          notes = "Robust standard errors not used here; this is for illustration only.",
          notes.align = "l"
          )
Sepal Length: Alternative Specifications
Dependent variable:
Sepal Length
Baseline Add Petal Length
(1) (2)
Sepal Width 0.884*** 0.231*
(0.162) (0.119)
Virginica 0.858***
(0.074)
Petal Length 0.472*** -0.503***
(0.107) (0.109)
Constant 3.488*** 1.642***
(0.453) (0.333)
Controls No Yes
Observations 100 100
R2 0.423 0.761
Adjusted R2 0.411 0.753
Residual Std. Error 0.509 (df = 97) 0.329 (df = 96)
F Statistic 35.484*** (df = 2; 97) 101.704*** (df = 3; 96)
Note: p<0.1; p<0.05; p<0.01
Robust standard errors not used here; this is for illustration only.

Saving Tables to a File

If you want to use the table in another document (for example, a LaTeX paper), you can save the output to a file with the out argument:

stargazer(fit1,
          type = "latex",
          title = "Regression Results",
          dep.var.labels = "Sepal Length",
          covariate.labels = c("Sepal Width", "Virginica"),
          digits = 3,
          out = "regression_table.tex"
          )
## 
## % Table created by stargazer v.5.2.3 by Marek Hlavac, Social Policy Institute. E-mail: marek.hlavac at gmail.com
## % Date and time: Mon, Jan 05, 2026 - 11:30:57 AM
## \begin{table}[!htbp] \centering 
##   \caption{Regression Results} 
##   \label{} 
## \begin{tabular}{@{\extracolsep{5pt}}lc} 
## \\[-1.8ex]\hline 
## \hline \\[-1.8ex] 
##  & \multicolumn{1}{c}{\textit{Dependent variable:}} \\ 
## \cline{2-2} 
## \\[-1.8ex] & Sepal Length \\ 
## \hline \\[-1.8ex] 
##  Sepal Width & 0.884$^{***}$ \\ 
##   & (0.162) \\ 
##   & \\ 
##  Virginica & 0.472$^{***}$ \\ 
##   & (0.107) \\ 
##   & \\ 
##  Constant & 3.488$^{***}$ \\ 
##   & (0.453) \\ 
##   & \\ 
## \hline \\[-1.8ex] 
## Observations & 100 \\ 
## R$^{2}$ & 0.423 \\ 
## Adjusted R$^{2}$ & 0.411 \\ 
## Residual Std. Error & 0.509 (df = 97) \\ 
## F Statistic & 35.484$^{***}$ (df = 2; 97) \\ 
## \hline 
## \hline \\[-1.8ex] 
## \textit{Note:}  & \multicolumn{1}{r}{$^{*}$p$<$0.1; $^{**}$p$<$0.05; $^{***}$p$<$0.01} \\ 
## \end{tabular} 
## \end{table}

This will create a file named regression_table.tex in your working directory.


Presenting t-test and z-test Results

We can also present t-test and z-test results. Here we will compare the mean sepal length of virginica and versicolor.

fit2 <- t.test(iris$Sepal.Length[iris$Species == 1],
               iris$Sepal.Length[iris$Species == 0],
               alternative = "two.sided",
               var.equal = FALSE,
               conf.level = 0.95)

fit2
## 
##  Welch Two Sample t-test
## 
## data:  iris$Sepal.Length[iris$Species == 1] and iris$Sepal.Length[iris$Species == 0]
## t = 5.6292, df = 94.025, p-value = 1.866e-07
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
##  0.4220269 0.8819731
## sample estimates:
## mean of x mean of y 
##     6.588     5.936

The raw t.test output is not in a table format yet. We can extract the pieces and put them into a small table using a matrix:

tt_df <- matrix(c("Virginica", "Versicolor",
                  fit2$estimate[2], fit2$estimate[1],
                  "T Statistic:", as.numeric(fit2$statistic),
                  "p-value:", fit2$p.value),
                nrow = 4, ncol = 2, byrow = TRUE)

tt_df
##      [,1]           [,2]                
## [1,] "Virginica"    "Versicolor"        
## [2,] "5.936"        "6.588"             
## [3,] "T Statistic:" "5.62916525971982"  
## [4,] "p-value:"     "1.866144387377e-07"

Now use stargazer to present that table:

stargazer(tt_df,
          type = "latex",
          summary = FALSE,
          title = "T-test: Virginica vs. Versicolor Sepal Length",
          digits = 3
          )
## 
## % Table created by stargazer v.5.2.3 by Marek Hlavac, Social Policy Institute. E-mail: marek.hlavac at gmail.com
## % Date and time: Mon, Jan 05, 2026 - 11:30:58 AM
## \begin{table}[!htbp] \centering 
##   \caption{T-test: Virginica vs. Versicolor Sepal Length} 
##   \label{} 
## \begin{tabular}{@{\extracolsep{5pt}} cc} 
## \\[-1.8ex]\hline 
## \hline \\[-1.8ex] 
## Virginica & Versicolor \\ 
## 5.936 & 6.588 \\ 
## T Statistic: & 5.62916525971982 \\ 
## p-value: & 1.866144387377e-07 \\ 
## \hline \\[-1.8ex] 
## \end{tabular} 
## \end{table}

Here:

You could also set type = "text" if you prefer a text-only table inside your R Markdown document.


A Cleaner Summary Table for t-tests

Sometimes you might want a cleaner summary table that includes the group means, standard deviations, and sample sizes. You can build this table as a small data frame and then feed it into stargazer.

t_summary <- iris %>%
  mutate(Species = ifelse(Species == 1, "Virginica", "Versicolor")) %>%
  group_by(Species) %>%
  summarize(
    mean_sepal_length = mean(Sepal.Length),
    sd_sepal_length   = sd(Sepal.Length),
    n                 = n(),
    .groups = "drop"
  )

t_summary
## # A tibble: 2 × 4
##   Species    mean_sepal_length sd_sepal_length     n
##   <chr>                  <dbl>           <dbl> <int>
## 1 Versicolor              5.94           0.516    50
## 2 Virginica               6.59           0.636    50

Now present this summary:

stargazer(t_summary,
          type = "html",
          summary = FALSE,
          title = "Summary Statistics: Sepal Length by Species",
          digits = 3,
          rownames = FALSE
          )
Summary Statistics: Sepal Length by Species
Species mean_sepal_length sd_sepal_length n
Versicolor 5.936 0.516171147063863 50
Virginica 6.588 0.635879593274432 50

You can then describe your t-test results in the text using math notation, for example:

\[ H_0: \mu_{\text{Virginica}} = \mu_{\text{Versicolor}} \quad\text{vs.}\quad H_A: \mu_{\text{Virginica}} \neq \mu_{\text{Versicolor}}. \]


Practice: Regression Table

Create your own regression table using stargazer.

  1. Fit the following two models:

    • Model A: Regress Sepal.Length on Petal.Length.
    • Model B: Regress Sepal.Length on Petal.Length and Species (using the 0/1 indicator we created).
  2. Use stargazer to display both models in a single table.

  3. Customize:

    • Give the table a title.
    • Use a meaningful dependent variable label (e.g., “Sepal Length (cm)”).
    • Replace variable names with more readable labels.
  4. Write 2–3 sentences interpreting the coefficient on Petal.Length. Use inline math notation for the hypotheses about that coefficient.


Practice: t-test Table

Now practice presenting a t-test result.

  1. Form two groups based on sepal width:

    • Group 1: Sepal.Width above the median.
    • Group 2: Sepal.Width at or below the median.
  2. Run a two-sample t-test comparing mean Sepal.Length across these two groups.

  3. Create a small table with:

    • Group labels.
    • Group means.
    • t statistic.
    • p-value.
  4. Display your table using stargazer and write a short paragraph interpreting the result. Be explicit about:

    • \(H_0\) and \(H_A\).
    • Whether you reject \(H_0\) at the 5% level.
    • Substantive interpretation in plain language.

Checklist Before You Knit

Before you knit your R Markdown document, check that:

Once everything looks good, knit your document to HTML and review the output as you would present it in a problem set or short paper.