| Sepal.Length | Sepal.Width | Petal.Length | Petal.Width | Species |
|---|---|---|---|---|
| 5.1 | 3.5 | 1.4 | 0.2 | setosa |
| 4.9 | 3.0 | 1.4 | 0.2 | setosa |
| 4.7 | 3.2 | 1.3 | 0.2 | setosa |
| 4.6 | 3.1 | 1.5 | 0.2 | setosa |
| 5.0 | 3.6 | 1.4 | 0.2 | setosa |
| 5.4 | 3.9 | 1.7 | 0.4 | setosa |
8 非交互表格
一些需要打印或出版的场景需要制作非交互的表格。R 语言社区也有不少 R 包可以制作所需表格,其中 gt 包非常值得介绍,它可以制作非常复杂的表格样式,表格定制能力很强,gt 包的设计遵循 ggplot2 的设计哲学,打造制作表格的语法。
8.1 快速入门
在前面的章节,我们已经遇到用 knitr 包的 kable() 函数制作的表格。
首先用 gt 包制作一个非常简单的 表 8.2 。
8.2 基础功能
8.2.1 添加标题
然后添加表格的标题和副标题,套上 md() 函数后,标题和副标题支持 Markdown 语法,告别 HTML 的制表方式吧!
| 鸢尾花数据集 | ||||
| R 内置数据集 | ||||
| Species | Sepal.Length | Sepal.Width | Petal.Length | Petal.Width |
|---|---|---|---|---|
| setosa | 5.1 | 3.5 | 1.4 | 0.2 |
| setosa | 4.9 | 3.0 | 1.4 | 0.2 |
| versicolor | 7.0 | 3.2 | 4.7 | 1.4 |
| versicolor | 6.4 | 3.2 | 4.5 | 1.5 |
| virginica | 6.3 | 3.3 | 6.0 | 2.5 |
| virginica | 5.8 | 2.7 | 5.1 | 1.9 |
8.2.2 重命名列
表格作为数据分类汇总和展示的工具,有时候原始数据的列名含义不够明确,需要重新命名。
| 种类 | 花萼长度 | 花萼宽度 | 花瓣长度 | 花瓣宽度 |
|---|---|---|---|---|
| setosa | 5.1 | 3.5 | 1.4 | 0.2 |
| setosa | 4.9 | 3.0 | 1.4 | 0.2 |
| versicolor | 7.0 | 3.2 | 4.7 | 1.4 |
| versicolor | 6.4 | 3.2 | 4.5 | 1.5 |
| virginica | 6.3 | 3.3 | 6.0 | 2.5 |
| virginica | 5.8 | 2.7 | 5.1 | 1.9 |
8.2.3 行列分组
行列分组的目的是让数据看起来更加清晰。让不同类型的行列分组,在数据上可以去重,在展示上表格看起来更加清爽。下表先按 Species 列进行行分组,再将剩余4列按花萼与花瓣分成两组。为了展示上的美观,在 Species 列前添加了行编号,调整表格宽度使之占页面宽度的 60%。
iris_dt |>
dplyr::mutate(row_id = dplyr::row_number(), .before = Species) |>
dplyr::group_by(Species) |>
gt(rowname_col = "row_id") |>
cols_label(
Species = "种类",
Sepal.Length = "长度",
Sepal.Width = "宽度",
Petal.Length = "长度",
Petal.Width = "宽度"
) |>
tab_spanner(
label = "花萼",
columns = starts_with("Sepal")
) |>
tab_spanner(
label = "花瓣",
columns = starts_with("Petal")
) |>
tab_options(
table.width = pct(60)
)
花萼
|
花瓣
|
|||
|---|---|---|---|---|
| 长度 | 宽度 | 长度 | 宽度 | |
| setosa | ||||
| 1 | 5.1 | 3.5 | 1.4 | 0.2 |
| 2 | 4.9 | 3.0 | 1.4 | 0.2 |
| versicolor | ||||
| 3 | 7.0 | 3.2 | 4.7 | 1.4 |
| 4 | 6.4 | 3.2 | 4.5 | 1.5 |
| virginica | ||||
| 5 | 6.3 | 3.3 | 6.0 | 2.5 |
| 6 | 5.8 | 2.7 | 5.1 | 1.9 |
8.2.4 填充颜色
在表格中填充颜色是为了突出和对比。gt 包提供函数 data_color() 来给表格上色,这个函数根据一组数据向量(表格中的某列)生成一组颜色值。下表根据列 Sepal.Length 的值和 viridis 调色板填充颜色。函数 data_color() 的参数 palette 可以接受来自 viridis 和 RColorBrewer 包的调色板的名称,如 “viridis”,也可以接受来自 paletteer 包的调色板,此时,指定调色板需要带所属的 R 包名,如 palette = "ggsci::red_material" 表示使用 ggsci 包的 red_material 调色板。
| 鸢尾花数据集 | ||||
| R 内置数据集 | ||||
| Species | Sepal.Length | Sepal.Width | Petal.Length | Petal.Width |
|---|---|---|---|---|
| setosa | 5.1 | 3.5 | 1.4 | 0.2 |
| setosa | 4.9 | 3.0 | 1.4 | 0.2 |
| versicolor | 7.0 | 3.2 | 4.7 | 1.4 |
| versicolor | 6.4 | 3.2 | 4.5 | 1.5 |
| virginica | 6.3 | 3.3 | 6.0 | 2.5 |
| virginica | 5.8 | 2.7 | 5.1 | 1.9 |
除了使用现成的 R 包中的调色板,还可以使用自定义调色板。函数 data_color() 的参数 fn 可以传递自定义的颜色生成函数,颜色映射函数 scales::col_numeric() 可以将数值转化为颜色向量。
| 鸢尾花数据集 | ||||
| R 内置数据集 | ||||
| Species | Sepal.Length | Sepal.Width | Petal.Length | Petal.Width |
|---|---|---|---|---|
| setosa | 5.1 | 3.5 | 1.4 | 0.2 |
| setosa | 4.9 | 3.0 | 1.4 | 0.2 |
| versicolor | 7.0 | 3.2 | 4.7 | 1.4 |
| versicolor | 6.4 | 3.2 | 4.5 | 1.5 |
| virginica | 6.3 | 3.3 | 6.0 | 2.5 |
| virginica | 5.8 | 2.7 | 5.1 | 1.9 |
8.2.5 添加脚注
类似添加表格标题和副标题,也可以添加脚注,且与表格的列指标关联。下表添加了两个脚注,一个与数据集中的 Sepal.Length 列关联,说明本数据集的来源,另一个脚注与列 Species 关联,说明其含义。
iris_dt |>
gt() |>
tab_header(
title = md("**鸢尾花**数据集"),
subtitle = "R 内置数据集"
) |>
data_color(
columns = "Sepal.Length",
method = "numeric", palette = "viridis", reverse = TRUE
) |>
data_color(
columns = "Species", palette = "Set1"
) |>
tab_footnote(
footnote = md("据说数据集最早收集自 Fisher's or Anderson's"),
locations = cells_column_labels(columns = "Sepal.Length")
) |>
tab_footnote(
footnote = "鸢尾花的类别",
locations = cells_column_labels(columns = "Species")
)| 鸢尾花数据集 | ||||
| R 内置数据集 | ||||
| Species1 | Sepal.Length2 | Sepal.Width | Petal.Length | Petal.Width |
|---|---|---|---|---|
| setosa | 5.1 | 3.5 | 1.4 | 0.2 |
| setosa | 4.9 | 3.0 | 1.4 | 0.2 |
| versicolor | 7.0 | 3.2 | 4.7 | 1.4 |
| versicolor | 6.4 | 3.2 | 4.5 | 1.5 |
| virginica | 6.3 | 3.3 | 6.0 | 2.5 |
| virginica | 5.8 | 2.7 | 5.1 | 1.9 |
| 1 鸢尾花的类别 | ||||
| 2 据说数据集最早收集自 Fisher’s or Anderson’s | ||||
8.3 扩展功能
8.3.1 输出格式
类似 ggplot2 包的函数 ggsave(),gt 包也有导出表格的函数 gtsave() ,下面将本章开头制作的简单表格保存为 PNG 格式图片。它还支持导出 HTML 、TeX 和 DOCX 等常见格式。
8.3.2 渲染公式
若表格中含有数学公式,支持 Markdown 语法。
8.3.3 添加水印
gt 包提供函数 local_image() 加载本地图片,可再用函数 html() 将图片数据渲染出来。
8.4 其它 R 包
8.4.1 gtExtras 包
gtExtras 包扩展 gt 包的能力,提供一些高级操作需要的函数,比如根据某一列的数值绘制条形图,这可以用一个函数 gt_plt_bar() 搞定。略有不足的是它仅支持 HTML 输出。如果需要 PNG 格式,调用函数 gtsave() 导出。
8.4.2 gtsummary 包
gtsummary 包 (Sjoberg 等 2021) 也是扩展 gt 包的能力,除了简单的数据汇总(类似基础函数 summary()),尤其可以根据统计模型的输出结果进行整理、汇总成表格。
| Characteristic |
setosa N = 501 |
versicolor N = 501 |
virginica N = 501 |
|---|---|---|---|
| Sepal.Length | 5.00 (4.80, 5.20) | 5.90 (5.60, 6.30) | 6.50 (6.20, 6.90) |
| Sepal.Width | 3.40 (3.20, 3.70) | 2.80 (2.50, 3.00) | 3.00 (2.80, 3.20) |
| Petal.Length | 1.50 (1.40, 1.60) | 4.35 (4.00, 4.60) | 5.55 (5.10, 5.90) |
| 1 Median (Q1, Q3) | |||
| Characteristic | Beta | 95% CI | p-value |
|---|---|---|---|
| Sepal.Width | 0.65 | 0.52, 0.78 | <0.001 |
| Petal.Length | 0.71 | 0.60, 0.82 | <0.001 |
| Petal.Width | -0.56 | -0.81, -0.30 | <0.001 |
| Abbreviation: CI = Confidence Interval | |||
除了 gt 包及其衍生包以外,另有两个制作表格的 R 包值得一提,分别是 tinytable 包和 kableExtra 包。
8.4.3 tinytable 包
顾名思义,tinytable 包是一个依赖极简的 R 包,这是一个最新出现的 R 包,与 tinyplot 包的设计同出于极简哲学。
| Species | Sepal.Length | Sepal.Width | Petal.Length | Petal.Width |
|---|---|---|---|---|
| setosa | 5.1 | 3.5 | 1.4 | 0.2 |
| setosa | 4.9 | 3.0 | 1.4 | 0.2 |
| versicolor | 7.0 | 3.2 | 4.7 | 1.4 |
| versicolor | 6.4 | 3.2 | 4.5 | 1.5 |
| virginica | 6.3 | 3.3 | 6.0 | 2.5 |
| virginica | 5.8 | 2.7 | 5.1 | 1.9 |
8.4.4 kableExtra 包
kableExtra 包主要是扩展了 knitr 包 kable() 函数的功能,相比于 gt 包,依赖更少,所以更加轻量。
library(knitr)
library(kableExtra)
options(kableExtra.html.bsTable = T)
iris_dt |>
kable(booktabs = TRUE, escape = FALSE, align = "c",
col.names = gsub("[.]", " ", names(iris_dt))) |>
kable_styling(
bootstrap_options = c("striped", "condensed"),
latex_options = "basic", full_width = FALSE
) |>
column_spec(1, color = "white", background = spec_color(as.integer(iris_dt$Species))) |>
column_spec(2, color = spec_color(iris_dt$Sepal.Length))| Species | Sepal Length | Sepal Width | Petal Length | Petal Width |
|---|---|---|---|---|
| setosa | 5.1 | 3.5 | 1.4 | 0.2 |
| setosa | 4.9 | 3.0 | 1.4 | 0.2 |
| versicolor | 7.0 | 3.2 | 4.7 | 1.4 |
| versicolor | 6.4 | 3.2 | 4.5 | 1.5 |
| virginica | 6.3 | 3.3 | 6.0 | 2.5 |
| virginica | 5.8 | 2.7 | 5.1 | 1.9 |