Getting Started with stargazer2

knitr::opts_chunk$set(
  collapse = TRUE,
  comment  = "",
  message  = FALSE,
  warning  = FALSE
)
library(stargazer2)

stargazer2 is a drop-in replacement for the stargazer package with native support for modern econometrics packages. For lm objects the output is designed to be identical to the original, with one key addition: the standard error type is always identified in the table note.

The primary output format is "latex" for embedding in papers. "text" provides a quick terminal preview without needing to compile anything.

Dataset

We use the wage1 dataset from the wooldridge package throughout this vignette. Three categorical variables are constructed from existing binary indicators.

library(wooldridge)
data(wage1)

wage1$region <- factor(
  ifelse(wage1$northcen == 1, "northcen",
  ifelse(wage1$south    == 1, "south",
  ifelse(wage1$west     == 1, "west", "northeast"))),
  levels = c("northeast", "northcen", "south", "west")
)

wage1$occupation <- factor(
  ifelse(wage1$profocc == 1, "professional",
  ifelse(wage1$clerocc == 1, "clerical",
  ifelse(wage1$servocc == 1, "service", "other"))),
  levels = c("other", "professional", "clerical", "service")
)

wage1$industry <- factor(
  ifelse(wage1$construc == 1, "construction",
  ifelse(wage1$ndurman  == 1, "nondurable_manuf",
  ifelse(wage1$trcommpu == 1, "transport",
  ifelse(wage1$trade    == 1, "trade",
  ifelse(wage1$services == 1, "services",
  ifelse(wage1$profserv == 1, "prof_services", "other")))))),
  levels = c("other", "construction", "nondurable_manuf",
             "transport", "trade", "services", "prof_services")
)

A familiar table

Four progressively richer log-wage specifications:

m1 <- lm(lwage ~ educ + exper + tenure, wage1)
m2 <- lm(lwage ~ educ + exper + tenure + female + married, wage1)
m3 <- lm(lwage ~ educ + exper + tenure + female + married +
            region + occupation, wage1)
m4 <- lm(lwage ~ educ + exper + tenure + female + married +
            region + occupation + industry, wage1)

A single call produces a publication-ready table. Models 3 and 4 include factor variables; omit suppresses their level dummies so the table stays focused on the economic variables of interest.

stargazer(m1, m2, m3, m4,
          type             = "text",
          title            = "Determinants of Log Wages",
          dep.var.labels   = "log(Wage)",
          covariate.labels = c("Education", "Experience", "Tenure",
                               "Female", "Married"),
          omit             = c("region", "occupation", "industry"),
          column.labels    = c("Baseline", "Demographics",
                               "Region/Occ.", "Full"),
          notes.append     = FALSE,
          notes            = "Controls for region, occupation, and industry in (3) and (4).")

Output formats

LaTeX (default)

The LaTeX source is what goes directly into your .tex file or via \input{}. Write to a file with out = "table.tex".

stargazer(m1, m2,
          type             = "latex",
          title            = "Determinants of Log Wages",
          label            = "tab:wage-ols",
          dep.var.labels   = "log(Wage)",
          covariate.labels = c("Education", "Experience", "Tenure"))

HTML

For use in R Markdown documents where a rendered table is more readable than LaTeX source:

stargazer(m1, m2,
          type             = "html",
          dep.var.labels   = "log(Wage)",
          covariate.labels = c("Education", "Experience", "Tenure"))

Custom standard errors via vcov

The vcov argument accepts a list of variance-covariance matrices — one per model. stargazer2 extracts the square root of the diagonal internally and updates the table note to name the SE type used in each column. This works with any function returning a matrix: sandwich::vcovHC, sandwich::vcovCL, or your own estimator.

HC1-robust SEs

library(sandwich)
stargazer(m1, m2, m3, m4,
          type             = "text",
          dep.var.labels   = "log(Wage)",
          covariate.labels = c("Education", "Experience", "Tenure",
                               "Female", "Married"),
          omit             = c("region", "occupation", "industry"),
          vcov             = list(vcovHC(m1, type = "HC1"),
                                  vcovHC(m2, type = "HC1"),
                                  vcovHC(m3, type = "HC1"),
                                  vcovHC(m4, type = "HC1")))

Industry-clustered SEs

stargazer(m1, m2, m3, m4,
          type             = "text",
          dep.var.labels   = "log(Wage)",
          covariate.labels = c("Education", "Experience", "Tenure",
                               "Female", "Married"),
          omit             = c("region", "occupation", "industry"),
          vcov             = list(vcovCL(m1, cluster = ~industry, data = wage1),
                                  vcovCL(m2, cluster = ~industry, data = wage1),
                                  vcovCL(m3, cluster = ~industry, data = wage1),
                                  vcovCL(m4, cluster = ~industry, data = wage1)))

Mixed SE types across columns

vcov entries need not be the same type across columns. When SE types differ, the note reports them by column group. Here column (1) uses HC1-robust SEs while columns (2)–(4) use industry-clustered SEs.

stargazer(m1, m2, m3, m4,
          type             = "latex",
          dep.var.labels   = "log(Wage)",
          covariate.labels = c("Education", "Experience", "Tenure",
                               "Female", "Married"),
          omit             = c("region", "occupation", "industry"),
          column.labels    = c("Baseline", "Demographics",
                               "Region/Occ.", "Full"),
          vcov             = list(vcovHC(m1, type = "HC1"),
                                  vcovCL(m2, cluster = ~industry, data = wage1),
                                  vcovCL(m3, cluster = ~industry, data = wage1),
                                  vcovCL(m4, cluster = ~industry, data = wage1)))

Cosmetic options

The most commonly used formatting arguments:

| Argument | Purpose | |---|---| | dep.var.labels | Override dependent variable name(s) | | covariate.labels | Rename coefficient rows (in display order) | | column.labels | Column headers beneath the dep-var line | | omit / keep | Regex patterns to drop or retain coefficient rows | | digits | Decimal places for all numbers | | star.cutoffs | P-value thresholds for significance stars | | notes / notes.append | Add or replace the automatic table note | | title / label | Caption and \label{} for LaTeX |

Table styles

The style argument selects a layout preset.

| Style | Layout | Significance note | |---|---|---| | "stargazer2" | Single \hline, full-width left-aligned note | p-value thresholds (default) | | "stargazer" | Matches original package exactly (double rules, \\[-1.8ex]) | p-value thresholds | | "aer" | American Economic Review — clean, no dep-var caption | Text descriptions ("Significant at the X percent level") | | "qje" | Quarterly Journal of Economics — like AER; observations labelled $N$ | Text descriptions |

stargazer(m1, m2,
          type             = "latex",
          dep.var.labels   = "log(Wage)",
          covariate.labels = c("Education", "Experience", "Tenure"),
          style            = "stargazer2")   # default
stargazer(m1, m2,
          type             = "latex",
          dep.var.labels   = "log(Wage)",
          covariate.labels = c("Education", "Experience", "Tenure"),
          style            = "aer")

Summary statistics

Passing a data frame instead of model objects produces a summary statistics table.

stargazer(
  wage1[, c("lwage", "educ", "exper", "tenure", "female", "married")],
  type             = "text",
  covariate.labels = c("log(Wage)", "Education", "Experience",
                       "Tenure", "Female", "Married")
)


Try the stargazer2 package in your browser

Any scripts or data that you put into this service are public.

stargazer2 documentation built on July 17, 2026, 5:08 p.m.