Skip to contents

This tutorial shows the full easytable workflow using palmerpenguins.

1) Fit a sequence of models

library(easytable)
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)

2) Create a readable baseline table

easytable(
  m1, m2, m3,
  model.names = c("Baseline", "With Species", "Full Model")
)

term

Baseline

With Species

Full Model

(Intercept)

-5780.83 ***
(305.81)

-4031.48 ***
(584.15)

-4047.52 ***
(585.52)

flipper_length_mm

49.69 ***
(1.52)

40.71 ***
(3.07)

41.09 ***
(3.09)

species:Chinstrap

-206.51 ***
(57.73)

-205.59 ***
(70.35)

species:Gentoo

266.81 ***
(95.26)

199.81 *
(109.71)

island:Dream

-59.75
(75.74)

island:Torgersen

-101.92
(77.65)

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

By default, each coefficient cell is two lines:

  1. Estimate + significance stars
  2. Standard error in parentheses

3) Highlight significant coefficients

easytable(
  m1, m2, m3,
  model.names = c("Baseline", "With Species", "Full Model"),
  highlight = TRUE
)

term

Baseline

With Species

Full Model

(Intercept)

-5780.83 ***
(305.81)

-4031.48 ***
(584.15)

-4047.52 ***
(585.52)

flipper_length_mm

49.69 ***
(1.52)

40.71 ***
(3.07)

41.09 ***
(3.09)

species:Chinstrap

-206.51 ***
(57.73)

-205.59 ***
(70.35)

species:Gentoo

266.81 ***
(95.26)

199.81 *
(109.71)

island:Dream

-59.75
(75.74)

island:Torgersen

-101.92
(77.65)

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

4) Collapse controls into indicator rows

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 ***
(305.81)

-4031.48 ***
(584.15)

-4047.52 ***
(585.52)

flipper_length_mm

49.69 ***
(1.52)

40.71 ***
(3.07)

41.09 ***
(3.09)

species:Chinstrap

-206.51 ***
(57.73)

-205.59 ***
(70.35)

species:Gentoo

266.81 ***
(95.26)

199.81 *
(109.71)

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

control.var is useful when models include many factor levels or fixed effects.

5) LaTeX output for PDF workflows

easytable(
  m1, m2, m3,
  model.names = c("Baseline", "With Species", "Full Model"),
  output = "latex",
  control.var = "island",
  highlight = TRUE
)

6) Robust standard errors (optional dependency path)

if (requireNamespace("lmtest", quietly = TRUE) &&
    requireNamespace("sandwich", quietly = TRUE)) {
  easytable(
    m1, m2, m3,
    model.names = c("Baseline", "With Species", "Full Model"),
    robust.se = TRUE
  )
}

term

Baseline

With Species

Full Model

(Intercept)

-5780.83 ***
(292.56)

-4031.48 ***
(542.24)

-4047.52 ***
(536.56)

flipper_length_mm

49.69 ***
(1.44)

40.71 ***
(2.86)

41.09 ***
(2.84)

species:Chinstrap

-206.51 ***
(52.21)

-205.59 ***
(66.68)

species:Gentoo

266.81 ***
(95.08)

199.81 *
(112.03)

island:Dream

-59.75
(82.45)

island:Torgersen

-101.92
(83.82)

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

7) Marginal effects (optional dependency path)

if (requireNamespace("margins", quietly = TRUE)) {
  easytable(
    m2, m3,
    model.names = c("With Species", "Full Model"),
    margins = TRUE
  )
}

term

With Species

Full Model

flipper_length_mm

40.71 ***
(3.07)

41.09 ***
(3.09)

species:Chinstrap

-206.51 ***
(57.73)

-205.59 ***
(70.35)

species:Gentoo

266.81 ***
(95.26)

199.81 *
(109.71)

island:Dream

-59.75
(75.74)

island:Torgersen

-101.92
(77.65)

N

342

342

R sq.

0.78

0.78

Adj. R sq.

0.78

0.78

Significance: ***p < .01; **p < .05; *p < .1

Note: Average Marginal Effects (AME)

8) Export outputs

easytable(
  m1, m2, m3,
  model.names = c("Baseline", "With Species", "Full Model"),
  highlight = TRUE,
  export.word = "penguins_table.docx",
  export.csv = "penguins_table.csv"
)

Design Notes

easytable keeps these display invariants:

  1. Two-line coefficient cells.
  2. Zebra only in coefficient rows.
  3. One divider between coefficient rows and model-stat rows.
  4. Control indicators in the model-stat block.

These defaults are intentional so tables remain legible in long workflows.