Lemon print – pretty printing data frames and tables

Stefan McKinnon Edwards sme@iysik.com

2024-11-10

This vignette demonstrates how load the lemon package automatically enables pretty printing of data frames with knitr’s kable.

The beauty of defining the function knit_print.data.frame is that when working with R Notebooks in R, the editor can output the data frame dynamically, while ensuring that the knitted document also has the

First we load some data and show the top.

data(USArrests)
head(USArrests)
##            Murder Assault UrbanPop Rape
## Alabama      13.2     236       58 21.2
## Alaska       10.0     263       48 44.5
## Arizona       8.1     294       80 31.0
## Arkansas      8.8     190       50 19.5
## California    9.0     276       91 40.6
## Colorado      7.9     204       78 38.7

Now load lemon and set the lemon_print functions.

library(lemon)
knit_print.data.frame <- lemon_print

The same view is now nicely printed!

```{r caption="Data frame is now printed using `kable`.",render=lemon_print}
head(USArrests)
```
Data frame is now printed using kable.
Murder Assault UrbanPop Rape
Alabama 13.2 236 58 21.2
Alaska 10.0 263 48 44.5
Arizona 8.1 294 80 31.0
Arkansas 8.8 190 50 19.5
California 9.0 276 91 40.6
Colorado 7.9 204 78 38.7

Notice how we specified kable arguments directly as chunk-options.

How it works

knitr uses a S3 generic function, knit_print, to print objects. Method dispatching in R means that by defining a function, say knit_print.data.frame, calling knit_print(df) will call our function if df was a data frame.

To have knitr use our function when outputting a data frame, we define the function knit_print.data.frame (and similar for data frames passed through dplyr functions, i.e tbl_df and grouped_df).

Disabling the function is by usual chunk options, render = normal_print. check ?knit_print.

Disabling the functions.

```{r normal_print,render=normal_print}
head(USArrests)
```
##            Murder Assault UrbanPop Rape
## Alabama      13.2     236       58 21.2
## Alaska       10.0     263       48 44.5
## Arizona       8.1     294       80 31.0
## Arkansas      8.8     190       50 19.5
## California    9.0     276       91 40.6
## Colorado      7.9     204       78 38.7

You can still ask for kable.

```{r results='asis',render=normal_print}
kable(head(USArrests),caption='Normal `kable` usage.')
```
Normal kable usage.
Murder Assault UrbanPop Rape
Alabama 13.2 236 58 21.2
Alaska 10.0 263 48 44.5
Arizona 8.1 294 80 31.0
Arkansas 8.8 190 50 19.5
California 9.0 276 91 40.6
Colorado 7.9 204 78 38.7

It uses kable

We have mentioned kable a couple of times. That is because the lemon_print for data frames uses kable of the knitr package.

Some common arguments:

Why does it matter

The second code block, when edited in RStudio, would look like this: Viewing data frames in R Notebooks in RStudio And, as demonstrated, the rendered document has the data frame printed nicely.

If we do not wish this behaviour, but still use kable,

kable(head(USArrests))
Murder Assault UrbanPop Rape
Alabama 13.2 236 58 21.2
Alaska 10.0 263 48 44.5
Arizona 8.1 294 80 31.0
Arkansas 8.8 190 50 19.5
California 9.0 276 91 40.6
Colorado 7.9 204 78 38.7

RStudio would look like this: RStudio renders kable’d data frames rather eh

Other objects covered

Summaries are nicely formatted, but these require setting the S3 method for table.

```{r kable.opts=list(caption='Summary tables are printed with some default options.')}
knit_print.table <- lemon_print
summary(USArrests)
```
Summary tables are printed with some default options.
Murder Assault UrbanPop Rape
Min. : 0.800 Min. : 45.0 Min. :32.00 Min. : 7.30
1st Qu.: 4.075 1st Qu.:109.0 1st Qu.:54.50 1st Qu.:15.07
Median : 7.250 Median :159.0 Median :66.00 Median :20.10
Mean : 7.788 Mean :170.8 Mean :65.54 Mean :21.23
3rd Qu.:11.250 3rd Qu.:249.0 3rd Qu.:77.75 3rd Qu.:26.18
Max. :17.400 Max. :337.0 Max. :91.00 Max. :46.00

Cross-tabulations are however not nicely formatted.

head(mtcars)
##                    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
## Hornet 4 Drive    21.4   6  258 110 3.08 3.215 19.44  1  0    3    1
## Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2
## Valiant           18.1   6  225 105 2.76 3.460 20.22  1  0    3    1
with(mtcars, table(cyl, gear))
##    gear
## cyl  3 4 5
##   4  1 8 2
##   6  2 4 1
##   8 12 0 2

dplyr

library(dplyr)
## 
## Attaching package: 'dplyr'
## The following object is masked from 'package:gridExtra':
## 
##     combine
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
knit_print.tbl <- lemon_print
```{r dplyr,kable.opts=list(caption='Also works on `dplyr` objects.')}
mtcars %>% group_by(cyl) %>% summarise(mean(disp))
```
Also works on dplyr objects.
cyl mean(disp)
4 105.1364
6 183.3143
8 353.1000