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 的制表方式吧!
library(data.table)
library(gt)
iris_dt <- as.data.table(iris)[, head(.SD, 2), by = .(Species)]
iris_dt |>
gt() |>
tab_header(
title = md("**鸢尾花**数据集"),
subtitle = "R 内置数据集"
)
鸢尾花数据集 | ||||
---|---|---|---|---|
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 重命名列
表格作为数据分类汇总和展示的工具,有时候原始数据的列名含义不够明确,需要重新命名。
iris_dt |>
gt() |>
cols_label(
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.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
调色板。
iris_dt |>
gt() |>
tab_header(
title = md("**鸢尾花**数据集"),
subtitle = "R 内置数据集"
) |>
data_color(
columns = "Sepal.Length",
palette = "viridis",
reverse = TRUE
)
鸢尾花数据集 | ||||
---|---|---|---|---|
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()
可以将数值转化为颜色向量。
iris_dt |>
gt() |>
tab_header(
title = md("**鸢尾花**数据集"),
subtitle = "R 内置数据集"
) |>
data_color(
columns = "Sepal.Length",
fn = scales::col_numeric(palette = "viridis", reverse = T, domain = NULL)
)
鸢尾花数据集 | ||||
---|---|---|---|---|
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()
),尤其可以根据统计模型的输出结果进行整理、汇总成表格。
library(gtsummary)
iris |>
tbl_summary(include = c(Sepal.Length, Sepal.Width, Petal.Length), by = Species)
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 包的设计同出于极简哲学。
library(tinytable)
tt(iris_dt, theme = "grid") |>
style_tt(i = 1:2, j = 1, color = "white", background = "#4B0055") |>
style_tt(i = 3:4, j = 1, color = "white", background = "#009B95") |>
style_tt(i = 5:6, j = 1, color = "white", background = "#FDE333")
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 |