\(~\)

My previous workflow was pretty tedious, as after preparing tables in R (data frames), I would export them to Excel, then copy from Excel into Word, and finally format the table in Word. Whenever I would make minor changes, it would take quite a bit of time to repeat these steps.

Fortunately, I found a package that suits my needs nicely, flextable. However, I only really need my tables in APA style (Times New Roman size 12, only horizontal lines, header row in bold, double-spaced, etc.), so I made a function just with the default settings I like to simplify my life.

Getting Started

Let’s first load the demo data. This data set comes with base R (meaning you have it too and can directly type this command into your R console).

data("mtcars")
# Let's take a smaller sample of this data for demonstration purposes.
(dataset <- head(mtcars[1:6]))
##                    mpg cyl disp  hp drat    wt
## Mazda RX4         21.0   6  160 110 3.90 2.620
## Mazda RX4 Wag     21.0   6  160 110 3.90 2.875
## Datsun 710        22.8   4  108  93 3.85 2.320
## Hornet 4 Drive    21.4   6  258 110 3.08 3.215
## Hornet Sportabout 18.7   8  360 175 3.15 3.440
## Valiant           18.1   6  225 105 2.76 3.460

Source the function from my github:

eval(parse("https://raw.githubusercontent.com/RemPsyc/niceplots/master/niceTableFunction.R", 
           encoding = 'UTF-8'))

Note: Here we cannot use the regular source() function because it involves special UTF-8 characters (i.e., greek letters for statistical symbols, such as Beta β, eta η, etc.)

\(~\)

Make the basic table

This will open the table in your RStudio viewer.

*Warning:* running the function below for the first time will install and load the following
packages (if they are not already installed and loaded on your machine): dplyr and flextable.
 Note: This will run many lines of code on your console and could take 5 minutes or more.
niceTable(dataset)

mpg

cyl

disp

hp

drat

wt

21.0

6

160

110

3.90

2.620

21.0

6

160

110

3.90

2.875

22.8

4

108

93

3.85

2.320

21.4

6

258

110

3.08

3.215

18.7

8

360

175

3.15

3.440

18.1

6

225

105

2.76

3.460

Save as object

We can save the flextable as an object, which we can later further edit, or export to another software (e.g., Microsoft Word).

my_table <- niceTable(dataset)

Save table to Word

save_as_docx(my_table, path = "~/nicetablehere.docx")
# This will save to, e.g., "C:/Users/Username/Documents/".
# You can change the path to where you would like to save it.
# If you do change the path manually, remember to use "R" slashes ('/' rather than '\').
# Also remember to specify the .docx extension of the file.

That’s it! Simple eh?

\(~\)


\(~\)

Publication-ready tables

Let’s setup a more ‘credible’ table with actual statistics for demonstration.

We first need a bit of complicated code to create a regression model and extract some relevant statistical information.

model <- lm(mpg ~ cyl * wt * disp, mtcars)
stats.table <- as.data.frame(summary(model)$coefficients)
stats.table <- cbind(row.names(stats.table), stats.table)
names(stats.table) <- c("Model", "B", "SE", "t", "p")
stats.table[c(2:4)] <- round(stats.table[c(2:4)], 2)
stats.table$p <- round(stats.table$p, 3)

The dataframe looks like this:

stats.table
##                   Model      B    SE     t     p
## (Intercept) (Intercept) 107.72 23.32  4.62 0.000
## cyl                 cyl -10.81  4.34 -2.49 0.020
## wt                   wt -24.76  8.47 -2.92 0.007
## disp               disp  -0.59  0.21 -2.79 0.010
## cyl:wt           cyl:wt   2.91  1.42  2.05 0.051
## cyl:disp       cyl:disp   0.08  0.03  2.81 0.010
## wt:disp         wt:disp   0.18  0.07  2.69 0.013
## cyl:wt:disp cyl:wt:disp  -0.02  0.01 -2.71 0.012

Now we can apply our function!

niceTable(stats.table)

Model

β

SE

t

p

(Intercept)

107.72

23.32

4.62

< .001

cyl

-10.81

4.34

-2.49

.020

wt

-24.76

8.47

-2.92

.007

disp

-0.59

0.21

-2.79

.010

cyl:wt

2.91

1.42

2.05

.051

cyl:disp

0.08

0.03

2.81

.010

wt:disp

0.18

0.07

2.69

.013

cyl:wt:disp

-0.02

0.01

-2.71

.012

As you can see, it automatically formatted the p, t, and SE values to italic, and the beta to β. It also formatted p values as < .001 and stripped the leading zeros (it will do the same for correlations r, R2, sr2).

Note: in order for this to work automatically, your columns must be named correctly. Currently the function will make the following conversions: p, t, SE, SD, M, F, b, r, and df to italic; R2 and sr2 to italic squared, np2 to italic η subscript-p squared, and B to β. Not seeing a symbol that should be there? Contact me and I’ll add it!

Let’s test this by simply changing our data frame names for the exercise.

test <- head(mtcars)
names(test) <- c("SD", "df", "M", "F", "b", "np2", "B", "p", "r", "R2", "sr2")
test[, 10:11] <- test[, 10:11]/10
niceTable(test)

SD

df

M

F

b

ηp2

β

p

r

R2

sr2

21.0

6

160

110

3.90

2.620

16.46

< .001

1.0

.40

.40

21.0

6

160

110

3.90

2.875

17.02

< .001

1.0

.40

.40

22.8

4

108

93

3.85

2.320

18.61

1.00

1.0

.40

.10

21.4

6

258

110

3.08

3.215

19.44

1.00

.00

.30

.10

18.7

8

360

175

3.15

3.440

17.02

< .001

.00

.30

.20

18.1

6

225

105

2.76

3.460

20.22

1.00

.00

.30

.10

\(~\)


\(~\)

Further editing

Often, one will need to tweak a table for a particular situation. Have no fear. This function outputs a flextable object, which can be ‘easily’ edited via the regular flextable functions. For an intro to flextable functions, see: https://cran.r-project.org/web/packages/flextable/vignettes/overview.html.

But just for a few quick formatting examples:

my_table %>%
  italic(j = 1, part = "body") %>%
  bg(bg = "gray", part = "header") %>%
  color(color = "blue", part = "header") %>%
  color(~ drat > 3.5, ~ drat + disp, color = "red") %>%
  bold(~ drat > 3.5, ~ wt + hp, bold = TRUE) %>%
  set_header_labels(mpg = "Miles/(US) gallon",
                    cyl = "Number of cylinders",
                    wt = "Weight (1000 lbs)")

Miles/(US) gallon

Number of cylinders

disp

hp

drat

Weight (1000 lbs)

21.0

6

160

110

3.90

2.620

21.0

6

160

110

3.90

2.875

22.8

4

108

93

3.85

2.320

21.4

6

258

110

3.08

3.215

18.7

8

360

175

3.15

3.440

18.1

6

225

105

2.76

3.460

\(~\)

\(~\)

Concluding Statement

Make sure to check out this page again if you use the code after a time or if you encounter errors, as I periodically update or improve the code.

You can always edit the function to suit your purposes, or contact me for questions or requests to modify this function at remitheriault.wixsite.com/site/contact! Thanks for reading my guide! :) \(~\)

\(~\)

\(~\)

\(~\)

\(~\)


Updated 2020-09-09

\(~\)

\(~\)

\(~\)

\(~\)

\(~\)

\(~\)