Useful packages

library(knitr)
library(kableExtra)
library(modelsummary)

rmarkdown

rmarkdown has the basic functionality to make very simple straightforward tables. Here are just a couple of examples, borrowing from Derek Sonderegger, Section 15.2

I often use an online tool, such as Table Maker. I can copy/paste into the form and get output in markdown, html or LaTeX.

Grid tables

What are called “grid tables” use “|” to separate columns and lines like “+——-+—-+” to separate rows. They don’t support Left/Center/Right alignment

+---------------+---------------+--------------------+
| Fruit         | Price         | Advantages         |
+===============+===============+====================+
| Bananas       | $1.34         | - built-in wrapper |
|               |               | - bright color     |
+---------------+---------------+--------------------+
| Oranges       | $2.10         | - cures scurvy     |
|               |               | - tasty            |
+---------------+---------------+--------------------+

You should not make them into chunks in .Rmd files. Just insert as ordinary text. The above gives:

Fruit Price Advantages
Bananas $1.34
  • built-in wrapper
  • bright color
Oranges $2.10
  • cures scurvy
  • tasty

Pipe tables

These rely on a special line just below the table header to control justification. Note the position of the “:”s to determine right, left, center.

| Right | Left | Default | Center |
|------:|:-----|---------|:------:|
|   12  |  12  |    12   |    12  |
|  123  |  123 |   123   |   123  |
|    1  |    1 |     1   |     1  |

This gives:

Right Left Default Center
12 12 12 12
123 123 123 123
1 1 1 1

I often find these ugly, because I can’t control the width of each column. However, you can include arbitrary markdown in the table cells.

|   Source    |  df  |   Sum of Sq   |    Mean Sq    |    F   |  $Pr(>F_{1,29})$    |
|:------------|-----:|--------------:|--------------:|-------:|--------------------:|
|  Girth      |  *1* |  7581.8       |  7581.8       | 419.26 |  **< 2.2e-16**      |
|  Residual   |  29  |  524.3        |   18.1        |        |                     |

Giving this result. (Why is it formatted full-width??)

Source df Sum of Sq Mean Sq F \(Pr(>F_{1,29})\)
Girth 1 7581.8 7581.8 419.26 < 2.2e-16
Residual 29 524.3 18.1

kable and kableExtra

knitr::kable(): Does a reasonably better job of formatting, for HTML & PDF output. Often, you can just create an output and pipe it, | kable(). Great for showing a part of a data set. This must be in a code chunk.

head(mtcars) |> dplyr::select(1:10) |> knitr::kable()

Output:

head(mtcars) |> dplyr::select(1:10) |> knitr::kable()
mpg cyl disp hp drat wt qsec vs am gear
Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4
Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4
Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4
Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3
Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0 0 3
Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0 3

Once you get the hang of this, you can take the next small steps to make your tables prettier with styles, themes, captions, etc. using kableExtra. See the vignette, Create Awesome HTML Table with knitr::kable and kableExtra.

library(knitr)
dat <- mtcars[1:8, 1:6]
dat |> kable(caption = "Some data on some cars", padding = 4)
Some data on some cars
mpg cyl disp hp drat wt
Mazda RX4 21.0 6 160.0 110 3.90 2.620
Mazda RX4 Wag 21.0 6 160.0 110 3.90 2.875
Datsun 710 22.8 4 108.0 93 3.85 2.320
Hornet 4 Drive 21.4 6 258.0 110 3.08 3.215
Hornet Sportabout 18.7 8 360.0 175 3.15 3.440
Valiant 18.1 6 225.0 105 2.76 3.460
Duster 360 14.3 8 360.0 245 3.21 3.570
Merc 240D 24.4 4 146.7 62 3.69 3.190

Add some style

Add some style. Note the use of full_width=FALSE to avoid the table being spread across the whole page. I haven’t quite figured out how to add the footnotes to appropriate places in the table.

library(kableExtra)
dat <- mtcars[1:8, 1:6]
dat |> 
  kable(caption = "**Some data on some cars**", padding = 5) |>
  kable_classic(html_font = "Arial Narrow", full_width = FALSE) |>
  add_footnote(label = c("footnote 1", "footnote 2"), notation = "symbol")
Some data on some cars
mpg cyl disp hp drat wt
Mazda RX4 21.0 6 160.0 110 3.90 2.620
Mazda RX4 Wag 21.0 6 160.0 110 3.90 2.875
Datsun 710 22.8 4 108.0 93 3.85 2.320
Hornet 4 Drive 21.4 6 258.0 110 3.08 3.215
Hornet Sportabout 18.7 8 360.0 175 3.15 3.440
Valiant 18.1 6 225.0 105 2.76 3.460
Duster 360 14.3 8 360.0 245 3.21 3.570
Merc 240D 24.4 4 146.7 62 3.69 3.190
* footnote 1
footnote 2

modelsummary package

The modelsummary package provides some quite comprenensive ways to summarize data and statistical models in R. See the paper Journal of Statistical Software paper. vignette

Simple crosstab

The formula is similar to that used by ftable: row_variables ~ column variables. There is also a statistic formula to control what statistics are calculated.

data("penguins", package = "palmerpenguins")
datasummary_crosstab(island ~ sex * species, 
                     statistic = 1 ~ 1 + N, 
                     data = penguins)
female
male
island Adelie Chinstrap Gentoo Adelie Chinstrap Gentoo All
Biscoe N 22 0 58 22 0 61 168
Dream N 27 34 0 28 34 0 124
Torgersen N 24 0 0 23 0 0 52
All N 73 34 58 73 34 61 344

By default, it also prints percents:

data("penguins", package = "palmerpenguins")
datasummary_crosstab(island ~ sex * species, 
                     data = penguins)
female
male
island Adelie Chinstrap Gentoo Adelie Chinstrap Gentoo All
Biscoe N 22 0 58 22 0 61 168
% row 13.1 0.0 34.5 13.1 0.0 36.3 100.0
Dream N 27 34 0 28 34 0 124
% row 21.8 27.4 0.0 22.6 27.4 0.0 100.0
Torgersen N 24 0 0 23 0 0 52
% row 46.2 0.0 0.0 44.2 0.0 0.0 100.0
All N 73 34 58 73 34 61 344
% row 21.2 9.9 16.9 21.2 9.9 17.7 100.0