library(apa7)
library(flextable)
library(ftExtra)
library(tidyverse)
library(easystats)
set_flextable_defaults(theme_fun = theme_apa,
font.family = "Times New Roman")
Making tables in APA style (Part 15 of 24)
In this 24-part series, each of the tables in Chapter 7 of the Publication Manual of the American Psychological Association (7th Edition) is recreated with apa7, flextable, easystats, and tidyverse functions.
- Automatic formatting of
lm
(linear model) analyses withapa_performance
andapa_compare_performance
.
Figure 1
Screenshot of the APA Manual’s Table 7.15

I love the easystats ecosystem. It provides a coherent framework for data-analysts to process and display statistical analyses. It makes so many previously tedious things simple. However, it was not specifically designed for the final display of APA tables. The apa7 package has a few functions and features that help process the output of easystats functions to make them table-ready.
First, lets simulate some data that resembles the data underlying the models in Figure 1, and create regression models for Models 1 and 2.
set.seed(1)
# sample size
<- 88
n
# simulated data
<- tibble(
d leader_gender = sample(0:1, n, replace = TRUE),
leader_sleep_condition = sample(0:1, 88, replace = TRUE),
charisma = 2.76 - .09 * leader_gender -
36 * leader_sleep_condition +
.rnorm(n, sd = 0.5))
# Models 1 and 2
<- lm(charisma ~ leader_gender, data = d)
m1 <- lm(charisma ~ leader_gender + leader_sleep_condition, data = d) m2
The parameters::parameters
function from the easystats ecosystem displays information about regression predictors.
parameters(m2)
Parameter | Coefficient | SE | 95% CI | t(85) | p
-----------------------------------------------------------------------------
(Intercept) | 2.79 | 0.08 | [ 2.62, 2.95] | 33.17 | < .001
leader gender | -0.20 | 0.10 | [-0.40, 0.00] | -1.96 | 0.054
leader sleep condition | -0.34 | 0.10 | [-0.55, -0.14] | -3.37 | 0.001
Uncertainty intervals (equal-tailed) and p-values (two-tailed) computed
using a Wald t-distribution approximation.
That is a really nice display. However, if we convert it directly with flextable
, we get something far less polished.
parameters(m2) |>
flextable()
Parameter | Coefficient | SE | CI | CI_low | CI_high | t | df_error | p |
---|---|---|---|---|---|---|---|---|
(Intercept) | 2.79 | 0.08 | 0.95 | 2.62 | 2.95 | 33.17 | 85 | 0.00 |
leader_gender | -0.20 | 0.10 | 0.95 | -0.40 | 0.00 | -1.96 | 85 | 0.05 |
leader_sleep_condition | -0.34 | 0.10 | 0.95 | -0.55 | -0.14 | -3.37 | 85 | 0.00 |
As it turns out, the output of the parameters
function undergoes a fair bit of processing before it prints. The output is a data.frame
with a parameters_model
class and many attributes that can be used by the easystats formatting functions. If we want to see the underlying data, we can convert the output to a data.frame
or tibble
.
parameters(m2) |>
as_tibble()
# A tibble: 3 × 9
Parameter Coefficient SE CI CI_low CI_high t df_error p
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <int> <dbl>
1 (Intercept) 2.79 0.0840 0.95 2.62 2.95 33.2 85 2.05e-50
2 leader_gender -0.200 0.102 0.95 -0.402 0.00312 -1.96 85 5.36e- 2
3 leader_sleep… -0.344 0.102 0.95 -0.547 -0.141 -3.37 85 1.13e- 3
If we really want just the output of parameters
as it displays, we use the insight::format_table
function.
parameters(m2, ci = .95) |>
::format_table() insight
Parameter Coefficient SE 95% CI t(85) p
1 (Intercept) 2.79 0.08 [ 2.62, 2.95] 33.17 < .001
2 leader gender -0.20 0.10 [-0.40, 0.00] -1.96 0.054
3 leader sleep condition -0.34 0.10 [-0.55, -0.14] -3.37 0.001
This gets us closer to APA style, but not quite all way there. We would like things to be nearly automatic and yet be able to fine-tune the output. Behold!
apa_parameters(m2)
# A tibble: 3 × 6
Variable `*B*` `*SE*` `β` `*t*(85)` `*p*`
<chr> <chr> <chr> <chr> <chr> <chr>
1 Constant 2.79 0.08 .00 33.17 <.001
2 Leader Gender −0.20 0.10 −.20 −1.96 .05
3 Leader Sleep Condition −0.34 0.10 −.34 −3.37 .001
The apa_parameters
function is a wrapper around the parameters
function with defaults that produce APA style output via markdown syntax. The columns are decimal aligned, statistics are italicized, the intercept is called a “Constant”, and the variable names are printed in title case.
Applying apa_flextable
to the output gives us perfect APA style:
apa_parameters(m2) |>
apa_flextable()
Variable | B | SE | β | t(85) | p |
---|---|---|---|---|---|
Constant | 2.79 | 0.08 | .00 | 33.17 | <.001 |
Leader Gender | −0.20 | 0.10 | −.20 | −1.96 | .05 |
Leader Sleep Condition | −0.34 | 0.10 | −.34 | −3.37 | .001 |
The apa_format_columns
function and a few others like apa_parameters
, apa_performance
, and apa_compare_performance
can process the output of the lm
function.
Getting the output of apa_parameters
and apa_compare_performance
into the same table requires a rather complex process. Eventually I’d like to automate some of these steps.
# pf <- column_formats()
# pf$SE@header <- "*SE*"
<- list(`Model 1` = m1,
m `Model 2` = m2)
<- apa_parameters(
d_parameters
m, predictor_parameters = c(
"Coefficient",
"Std_Coefficient",
"SE"))
<- apa_performance_comparison(
d_performance
m,metrics = c("R2", "deltaR2"),
starred = "deltaR2") |>
pivot_longer(-Model, names_to = "Variable") |>
mutate(Model = paste0(Model, "_β")) |>
pivot_wider(names_from = Model)
|>
d_parameters pivot_wider_name_first(
id_cols = Variable,
names_from = Model,
values_from = 3:5) |>
mutate(Variable = str_to_sentence(Variable)) |>
add_row(d_performance) |>
mutate(across(-Variable, \(x) align_chr(
x,center = "\\.",
side = "left",
NA_value = "") |>
star_balance())) |>
apa_flextable(no_format_columns = Variable) |>
align(j = 1, align = "left") |>
::add_footer_lines(values = as_paragraph_md("*Note*. *N* = 88. We examined the impact of leader sleep condition (control vs. sleep deprived) on ratings of charismatic leadership. In Models 1 and 2, we entered the control variable of leader gender to predict leader charisma.")) |>
flextablefootnote(i = 2,
j = 1,
value = as_paragraph("Male = 1, female = 2. "),
ref_symbols = "a ") |>
footnote(i = 3,
j = 1,
value = as_paragraph(
"Control condition = 0, sleep-deprived condition = 1"),
ref_symbols = "b ",
inline = T,
sep = ".") |>
add_footer_lines(
values = as_paragraph_md("\\* *p* < .05. \\*\\* *p* < .01.")) |>
align(align = "left", part = "footer")
Table 1
Regression Coefficients of Leader Sleep on Charismatic Leadership
Variable | Model 1 | Model 2 | |||||
---|---|---|---|---|---|---|---|
B | β | SE | B | β | SE | ||
Constant | 2.65 | .00 | 0.08 | 2.79 | .00 | 0.08 | |
Leader gendera | −0.24 | −.23 | 0.11 | −0.20 | −.20 | 0.10 | |
Leader sleep conditionb | −0.34 | −.34 | 0.10 | ||||
R2 | .06 | .17 | |||||
ΔR2 | .11** | ||||||
Note. N = 88. We examined the impact of leader sleep condition (control vs. sleep deprived) on ratings of charismatic leadership. In Models 1 and 2, we entered the control variable of leader gender to predict leader charisma. | |||||||
a Male = 1, female = 2. b Control condition = 0, sleep-deprived condition = 1. | |||||||
* p < .05. ** p < .01. |
Citation
@misc{schneider2025,
author = {Schneider, W. Joel},
title = {Recreating {APA} {Manual} {Table} 7.15 in {R} with Apa7},
date = {2025-09-25},
url = {https://wjschne.github.io/posts/apatables/apa715.html},
langid = {en}
}