# If you do not have devtools installed run:
install.packages("devtools")easytable 2.1.0
Design-first regression tables for Word, HTML, and PDF
About easytable
easytable is a small R package for producing regression tables with stable defaults. The aim is to make it easy to get a clean table that looks consistent across outputs and is comfortable to read. It prioritizes ease-of-use and design over flexibility and for now only support lm and glm models.
Installation
easytable is installed from this GitHub repository. You may need to install the devtools library first!
# Otherwise, run:
devtools::install_github("alfredo-hs/easytable")A simple table
The simplest workflow is to fit a model and pass it to easytable().
library(easytable)
model <- lm(mpg ~ wt, data = mtcars)
easytable(model)term | Model 1 |
|---|---|
(Intercept) | 37.29 *** |
wt | -5.34 *** |
N | 32 |
R sq. | 0.75 |
Adj. R sq. | 0.74 |
Significance: ***p < .01; **p < .05; *p < .1 | |
Multiple models side by side
Below is a slightly richer example using the famous palmerpenguins dataset. We estimate a small sequence of models and then render them in a single table.
library(palmerpenguins)
m1 <- lm(body_mass_g ~ flipper_length_mm, data = penguins)
m2 <- lm(body_mass_g ~ flipper_length_mm + species, data = penguins)
m3 <- lm(body_mass_g ~ flipper_length_mm + species + island, data = penguins)easytable(m1, m2, m3)term | Model 1 | Model 2 | Model 3 |
|---|---|---|---|
(Intercept) | -5780.83 *** | -4031.48 *** | -4047.52 *** |
flipper_length_mm | 49.69 *** | 40.71 *** | 41.09 *** |
species:Chinstrap | -206.51 *** | -205.59 *** | |
species:Gentoo | 266.81 *** | 199.81 * | |
island:Dream | -59.75 | ||
island:Torgersen | -101.92 | ||
N | 342 | 342 | 342 |
R sq. | 0.76 | 0.78 | 0.78 |
Adj. R sq. | 0.76 | 0.78 | 0.78 |
Significance: ***p < .01; **p < .05; *p < .1 | |||
You can provide model labels to keep the table readable.
easytable(
m1, m2, m3,
model.names = c("Baseline", "With species", "Full model")
)term | Baseline | With species | Full model |
|---|---|---|---|
(Intercept) | -5780.83 *** | -4031.48 *** | -4047.52 *** |
flipper_length_mm | 49.69 *** | 40.71 *** | 41.09 *** |
species:Chinstrap | -206.51 *** | -205.59 *** | |
species:Gentoo | 266.81 *** | 199.81 * | |
island:Dream | -59.75 | ||
island:Torgersen | -101.92 | ||
N | 342 | 342 | 342 |
R sq. | 0.76 | 0.78 | 0.78 |
Adj. R sq. | 0.76 | 0.78 | 0.78 |
Significance: ***p < .01; **p < .05; *p < .1 | |||
Highlighting and readability
easytable is opinionated about readability. The coefficient block uses zebra shading by default, and highlight = TRUE can emphasize statistically significant results in a way that stays consistent across outputs.
easytable(
m1, m2, m3,
model.names = c("Baseline", "With species", "Full model"),
highlight = TRUE
)term | Baseline | With species | Full model |
|---|---|---|---|
(Intercept) | -5780.83 *** | -4031.48 *** | -4047.52 *** |
flipper_length_mm | 49.69 *** | 40.71 *** | 41.09 *** |
species:Chinstrap | -206.51 *** | -205.59 *** | |
species:Gentoo | 266.81 *** | 199.81 * | |
island:Dream | -59.75 | ||
island:Torgersen | -101.92 | ||
N | 342 | 342 | 342 |
R sq. | 0.76 | 0.78 | 0.78 |
Adj. R sq. | 0.76 | 0.78 | 0.78 |
Significance: ***p < .01; **p < .05; *p < .1 | |||
Control variables and fixed effects
When models include many levels from a factor, tables can become hard to scan. control.var is intended to help by grouping or compactly representing a named set of controls.
easytable(
m1, m2, m3,
model.names = c("Baseline", "With species", "Full model"),
control.var = "island",
highlight = TRUE
)term | Baseline | With species | Full model |
|---|---|---|---|
(Intercept) | -5780.83 *** | -4031.48 *** | -4047.52 *** |
flipper_length_mm | 49.69 *** | 40.71 *** | 41.09 *** |
species:Chinstrap | -206.51 *** | -205.59 *** | |
species:Gentoo | 266.81 *** | 199.81 * | |
island | Y | ||
N | 342 | 342 | 342 |
R sq. | 0.76 | 0.78 | 0.78 |
Adj. R sq. | 0.76 | 0.78 | 0.78 |
Significance: ***p < .01; **p < .05; *p < .1 | |||
Exporting to Word and CSV
If you are working in Word, you can export a .docx directly. You can also export a .csv for quick inspection or for downstream workflows.
easytable(
m1, m2, m3,
model.names = c("Baseline", "With species", "Full model"),
highlight = TRUE,
export.word = "penguins_table.docx",
export.csv = "penguins_table.csv"
)Robust standard errors
easytable can compute robust standard errors when the required packages are installed.
library(lmtest)
library(sandwich)
easytable(
m1, m2, m3,
model.names = c("Baseline", "With species", "Full model"),
robust.se = TRUE
)term | Baseline | With species | Full model |
|---|---|---|---|
(Intercept) | -5780.83 *** | -4031.48 *** | -4047.52 *** |
flipper_length_mm | 49.69 *** | 40.71 *** | 41.09 *** |
species:Chinstrap | -206.51 *** | -205.59 *** | |
species:Gentoo | 266.81 *** | 199.81 * | |
island:Dream | -59.75 | ||
island:Torgersen | -101.92 | ||
N | 342 | 342 | 342 |
R sq. | 0.76 | 0.78 | 0.78 |
Adj. R sq. | 0.76 | 0.78 | 0.78 |
Significance: ***p < .01; **p < .05; *p < .1 | |||
Note: Robust Standard Errors | |||
What to test and how to report issues
If you would like to contribute, opening an issue on GitHub with a minimal example is enough. If you are experimenting with AI-assisted changes, feel free to fork the repo and propose a small, focused pull request.