Skip to contents

Make nice APA tables easily through a wrapper around the flextable package with sensical defaults and automatic formatting features.

Usage

nice_table(
  data,
  highlight = FALSE,
  italics,
  col.format.p,
  col.format.r,
  format.custom,
  col.format.custom,
  width = 1,
  broom = "",
  report = "",
  short = FALSE,
  title,
  footnote,
  separate.header
)

Arguments

data

The data frame, to be converted to a flextable. The data frame cannot have duplicate column names.

highlight

Highlight rows with statistically significant results? Requires a column named "p" containing p-values. Can either accept logical (TRUE/FALSE) OR a numeric value for a custom critical p-value threshold (e.g., 0.10 or 0.001).

italics

Which columns headers should be italic? Useful for column names that should be italic but that are not picked up automatically by the function. Select with numerical range, e.g., 1:3.

col.format.p

Applies p-value formatting to columns that cannot be named "p" (for example for a data frame full of p-values, also because it is not possible to have more than one column named "p"). Select with numerical range, e.g., 1:3.

col.format.r

Applies r-value formatting to columns that cannot be named "r" (for example for a data frame full of r-values, also because it is not possible to have more than one column named "r"). Select with numerical range, e.g., 1:3.

format.custom

Applies custom formatting to columns selected via the col.format.custom argument. This is useful if one wants custom formatting other than for p- or r-values. It can also be used to transform (e.g., multiply) certain values or print a specific symbol along the values for instance.

col.format.custom

Which columns to apply the custom function to. Select with numerical range, e.g., 1:3.

width

Width of the table, in percentage of the total width, when exported e.g., to Word.

broom

If providing a tidy table produced with the broom package, which model type to use if one wants automatic formatting (options are "t.test", "lm", "cor.test", and "wilcox.test").

report

If providing an object produced with the report package, which model type to use if one wants automatic formatting (options are "t.test", "lm", and "cor.test").

short

Logical. Whether to return an abbreviated version of the tables made by the report package.

title

Optional, to add a table header, if desired.

footnote

Optional, to add a table footnote (or more), if desired.

separate.header

Logical, whether to separate headers based on name delimiters (i.e., periods ".").

Examples

# Make the basic table
my_table <- nice_table(mtcars[1:3, ],
  title = "Motor Trend Car Road Tests",
  footnote = "1974 Motor Trend US magazine."
)
my_table
#> a flextable object.
#> col_keys: `mpg`, `cyl`, `disp`, `hp`, `drat`, `wt`, `qsec`, `vs`, `am`, `gear`, `carb` 
#> header has 2 row(s) 
#> body has 3 row(s) 
#> original dataset sample: 
#>                mpg cyl disp  hp drat    wt  qsec vs am gear carb
#> Mazda RX4     21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
#> Mazda RX4 Wag 21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
#> Datsun 710    22.8   4  108  93 3.85 2.320 18.61  1  1    4    1

if (FALSE) {
# Save table to word
save_as_docx(my_table, path = "nicetablehere.docx")
}

# Publication-ready tables
mtcars.std <- lapply(mtcars, scale)
model <- lm(mpg ~ cyl + wt * hp, mtcars.std)
stats.table <- as.data.frame(summary(model)$coefficients)
CI <- confint(model)
stats.table <- cbind(
  row.names(stats.table),
  stats.table, CI
)
names(stats.table) <- c(
  "Term", "B", "SE", "t", "p",
  "CI_lower", "CI_upper"
)
nice_table(stats.table, highlight = TRUE)
#> a flextable object.
#> col_keys: `Term`, `B`, `SE`, `t`, `p`, `95% CI` 
#> header has 1 row(s) 
#> body has 5 row(s) 
#> original dataset sample: 
#>                    Term          B         SE          t            p
#> (Intercept) (Intercept) -0.1835269 0.08532112 -2.1510135 4.058431e-02
#> cyl                 cyl -0.1082286 0.15071576 -0.7180977 4.788652e-01
#> wt                   wt -0.6230206 0.10927573 -5.7013627 4.663587e-06
#> hp                   hp -0.2874898 0.11955935 -2.4045781 2.331865e-02
#> wt:hp             wt:hp  0.2875867 0.08895462  3.2329593 3.221753e-03
#>                     95% CI signif
#> (Intercept) [-0.36, -0.01]   TRUE
#> cyl          [-0.42, 0.20]  FALSE
#> wt          [-0.85, -0.40]   TRUE
#> hp          [-0.53, -0.04]   TRUE
#> wt:hp         [0.11, 0.47]   TRUE

# Test different column names
test <- head(mtcars)
names(test) <- c(
  "dR", "N", "M", "SD", "b", "np2",
  "ges", "p", "r", "R2", "sr2"
)
test[, 10:11] <- test[, 10:11] / 10
nice_table(test)
#> a flextable object.
#> col_keys: `dR`, `N`, `M`, `SD`, `b`, `np2`, `ges`, `p`, `r`, `R2`, `sr2` 
#> header has 1 row(s) 
#> body has 6 row(s) 
#> original dataset sample: 
#>                     dR N   M  SD    b   np2   ges p r  R2 sr2
#> Mazda RX4         21.0 6 160 110 3.90 2.620 16.46 0 1 0.4 0.4
#> Mazda RX4 Wag     21.0 6 160 110 3.90 2.875 17.02 0 1 0.4 0.4
#> Datsun 710        22.8 4 108  93 3.85 2.320 18.61 1 1 0.4 0.1
#> Hornet 4 Drive    21.4 6 258 110 3.08 3.215 19.44 1 0 0.3 0.1
#> Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0 0 0.3 0.2

# Custom cell formatting (such as p or r)
nice_table(test[8:11], col.format.p = 2:4, highlight = .001)
#> a flextable object.
#> col_keys: `p`, `r`, `R2`, `sr2` 
#> header has 1 row(s) 
#> body has 6 row(s) 
#> original dataset sample: 
#>                   p r  R2 sr2 signif
#> Mazda RX4         0 1 0.4 0.4   TRUE
#> Mazda RX4 Wag     0 1 0.4 0.4   TRUE
#> Datsun 710        1 1 0.4 0.1  FALSE
#> Hornet 4 Drive    1 0 0.3 0.1  FALSE
#> Hornet Sportabout 0 0 0.3 0.2   TRUE

nice_table(test[8:11], col.format.r = 1:4)
#> a flextable object.
#> col_keys: `p`, `r`, `R2`, `sr2` 
#> header has 1 row(s) 
#> body has 6 row(s) 
#> original dataset sample: 
#>                   p r  R2 sr2
#> Mazda RX4         0 1 0.4 0.4
#> Mazda RX4 Wag     0 1 0.4 0.4
#> Datsun 710        1 1 0.4 0.1
#> Hornet 4 Drive    1 0 0.3 0.1
#> Hornet Sportabout 0 0 0.3 0.2

# Apply custom functions to cells
fun <- function(x) {
  x + 11.1
}
nice_table(test[8:11], col.format.custom = 2:4, format.custom = "fun")
#> Error in set_formatter(., r = fun): object 'fun' not found

fun <- function(x) {
  paste("x", x)
}
nice_table(test[8:11], col.format.custom = 2:4, format.custom = "fun")
#> Error in set_formatter(., r = fun): object 'fun' not found

# Separate headers based on periods
header.data <- structure(list(
  Variable = c(
    "Sepal.Length",
    "Sepal.Width", "Petal.Length"
  ), setosa.M = c(
    5.01, 3.43,
    1.46
  ), setosa.SD = c(0.35, 0.38, 0.17), versicolor.M =
    c(5.94, 2.77, 4.26), versicolor.SD = c(0.52, 0.31, 0.47)
),
row.names = c(NA, -3L), class = "data.frame"
)
nice_table(header.data,
  separate.header = TRUE,
  italics = 2:4
)
#> a flextable object.
#> col_keys: `Variable`, `setosa.M`, `setosa.SD`, `versicolor.M`, `versicolor.SD` 
#> header has 2 row(s) 
#> body has 3 row(s) 
#> original dataset sample: 
#>       Variable setosa.M setosa.SD versicolor.M versicolor.SD
#> 1 Sepal.Length     5.01      0.35         5.94          0.52
#> 2  Sepal.Width     3.43      0.38         2.77          0.31
#> 3 Petal.Length     1.46      0.17         4.26          0.47