The flextable and gt packages have many, many options and helper functions. The tabulator
, summarizor
, and proc_freq
functions from the flextable package are particularly powerful ways of summarizing and describing data. Functions that automate your descriptive statistics tables for you (e.g., the amazing gtsummary package) inevitably entail some level of compromise. It is unreasonable for a single function to anticipate the diversity of needs out there. Sometimes you need a table to be a particular way, and you need to do the heaving lifting yourself. After all that, the apa_style
function will get a flextable or gt table close to APA style. You may need to do some additional styling with flextable or gt as well.
Here I create a table of means, standard deviations, and sample sizes for several variables across groups. The particulars are not so important here, just that flextable and gt can do most of the rest after that.
Data Setup
d <- diamonds %>%
select(cut, price, carat, depth, table) %>%
arrange(cut) %>%
rename_with(str_to_title) %>%
pivot_longer(where(is.numeric), names_to = "Variable") %>%
summarise(
M = mean(value, na.rm = TRUE),
SD = sd(value, na.rm = TRUE),
n = n(),
.by = c(Variable, Cut)) %>%
pivot_longer(c(M, SD)) %>%
unite(Variable, Variable, name) %>%
pivot_wider(names_from = Variable)
Flextable
The flextable package has a theme_apa
function that can get things very close to full APA style. With a little extra care, the formatting in Table 1 is pretty much perfect.
flextable::flextable(d) |>
theme_apa() |>
flextable::separate_header() |>
colformat_double(j = 3:4,
prefix = "$",
digits = 2) |>
italic(j = -1, i = 2, part = "header") |>
italic(j = 2, i = 1, part = "header") |>
align(align = "center", part = "header") |>
align(j = 1) |>
surround(
i = 2,
part = "header",
border.top = flextable::fp_border_default(
color = "black",
width = 1)
)
flextable
Cut |
n |
Price |
Carat |
Depth |
Table |
||||
---|---|---|---|---|---|---|---|---|---|
M |
SD |
M |
SD |
M |
SD |
M |
SD |
||
Fair |
1,610 |
$4,358.76 |
$3,560.39 |
1.05 |
0.52 |
64.04 |
3.64 |
59.05 |
3.95 |
Good |
4,906 |
$3,928.86 |
$3,681.59 |
0.85 |
0.45 |
62.37 |
2.17 |
58.69 |
2.85 |
Very Good |
12,082 |
$3,981.76 |
$3,935.86 |
0.81 |
0.46 |
61.82 |
1.38 |
57.96 |
2.12 |
Premium |
13,791 |
$4,584.26 |
$4,349.20 |
0.89 |
0.52 |
61.26 |
1.16 |
58.75 |
1.48 |
Ideal |
21,551 |
$3,457.54 |
$3,808.40 |
0.70 |
0.43 |
61.71 |
0.72 |
55.95 |
1.25 |
The apa_flextable
function
The apa_flextable
function handles most of the formatting automatically except for the dollar signs, which flextable can add later. Table 2 also decimal aligns all the numbers, though this is apparent in column n
only.
d |>
apa_flextable() |>
colformat_char(j = 3:4, prefix = "$")
apa_flextable
Cut |
n |
Price |
Carat |
Depth |
Table |
|||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
M |
SD |
M |
SD |
M |
SD |
M |
SD |
|||||
Fair |
1,610 |
$4,358.76 |
$3,560.39 |
1.05 |
0.52 |
64.04 |
3.64 |
59.05 |
3.95 |
|||
Good |
4,906 |
$3,928.86 |
$3,681.59 |
0.85 |
0.45 |
62.37 |
2.17 |
58.69 |
2.85 |
|||
Very Good |
12,082 |
$3,981.76 |
$3,935.86 |
0.81 |
0.46 |
61.82 |
1.38 |
57.96 |
2.12 |
|||
Premium |
13,791 |
$4,584.26 |
$4,349.20 |
0.89 |
0.52 |
61.26 |
1.16 |
58.75 |
1.48 |
|||
Ideal |
21,551 |
$3,457.54 |
$3,808.40 |
0.70 |
0.43 |
61.71 |
0.72 |
55.95 |
1.25 |