ixxmu / mp_duty

抓取网络文章到github issues保存
https://archives.duty-machine.now.sh/
89 stars 24 forks source link

「R」使用gt包创建表格 #393

Closed ixxmu closed 3 years ago

ixxmu commented 3 years ago

https://mp.weixin.qq.com/s/NI1qp8yql6znP1VhMBhjYw

github-actions[bot] commented 3 years ago

「R」使用gt包创建表格 by 优雅R

看到 gt 包终于被宣告提交到 CRAN 了。这个包挂在 GitHub 上非常久了,基于它包好像都有几个。我今天把冷饭拿出来再炒一炒,或许有读者会喜欢。另外,该包作者将表格相关的包做了个汇总,我也把它更新到了本文的下方。本文应当可以成为读者使用 R 构建表格的一大入口,值得点赞收藏。

RStudio 提供了出版级的表格解决方案gt包。


安装:

remotes::install_github("rstudio/gt")

gt包所做的一切都是为了更简单地生成好看的展示表格。展示表格?是的,我们正在尝试将数据表格(如tibbles、data.frame)和你在网页、期刊文章或者杂志中的表格区分开来。后面这种表格可以称为展示表格、汇总表格或者真实的表格。下面是一些网站上的例子:

我们可以认为展示表格仅是输出,我们不想要把它作为输入(数据)。其他包含注释、表格元素风格以及文本转换的特征用于更好更清楚地表达主题。

使用简单的表格展示gt基础

让我们使用一个R datasets包中不是很流行的数据集islands:它是一个命名向量。我们使用dplyr根据它准备一个tibble:

# 获取世界10个最大的大陆
islands_tbl <-
dplyr::tibble(
name = names(islands),
size = islands
) %>%
dplyr::arrange(desc(size)) %>%
dplyr::slice(1:10)

# 显示表
islands_tbl
#> # A tibble: 10 x 2
#> name size
#> <chr> <dbl>
#> 1 Asia 16988
#> 2 Africa 11506
#> 3 North America 9390
#> 4 South America 6795
#> 5 Antarctica 5500
#> 6 Europe 3745
#> 7 Australia 2968
#> 8 Greenland 840
#> 9 New Guinea 306
#> 10 Borneo 280

因为islands_tbl是一个tibble,我们现在有了gt的合适输入。 顺便说一下,我们也可以使用简单的数据框作为输入。

gt API的主指令是gt()函数。如果我们将上面的数据传入进去,我们将得到一个gt Table

# 创建一个显示表格
gt_tbl <- gt(data = islands_tbl)

# 展示表格
gt_tbl

这已经不错了。虽然它非常地基础,不过我们确实拿到了一个有合适列标签的表格。然而有时候,我们想要它更好看一些:一个表格标题、子标题,有时候还要脚注和来源说明。

给简单的表格加点料

gt包可以通过添加要素来让结果的gt Table更好地表达你所要展示的信息。前面的gt Table仅展示了两种要素,即Column Labels(列标签)和Table Body(表格主体)。接下来的例子会展示目前可以使用的其他表格要素。

一个表格的所有要素可以和谐地统一。

要素(从上到下)包括:

  • 表格头部 (可选,包含标题以及可能得子标题)
  • 根头 (可选,包含行组标签、行标签和汇总标签)
  • 列标签 (包含列标签和跨组列标签)
  • 表主体  (包含单元格)
  • 表格脚部 (可选,包含脚注和源注释)

我们使用tab_*()函数家族添加各种要素。添加表格头部是非常容易的,让我们看看先前的表格有了标题和子标题会怎么样。我们使用tab_header()函数。

# 在列标签上方添加头部信息
gt_tbl <-
gt_tbl %>%
tab_header(
title = "Large Landmasses of the World",
subtitle = "The top ten largest are presented"
)

# Show the gt Table
gt_tbl

头部要素提供了描述所展示数据的地方。我们可以使用Markdow来格式化标题和子标题,这可以通过md()函数实现。

下面是一个例子:

# 使用markdown将标题和子标题分别加粗和斜体化
gt(islands_tbl[1:2,]) %>%
tab_header(
title = md("**Large Landmasses of the World**"),
subtitle = md("The *top two* largest are presented")
)

使用tab_source_note()函数可以在表格底部添加源注释。它除了可以使用markdown,还可以调用多次。

# 添加2个源注释
gt_tbl <-
gt_tbl %>%
tab_source_note(
source_note = "Source: The World Almanac and Book of Facts, 1975, page 406."
) %>%
tab_source_note(
source_note = md("Reference: McNeil, D. R. (1977) *Interactive Data Analysis*. Wiley.")
)

# Show the gt Table
gt_tbl

脚注位于脚部要素,它们的引用会被粘贴到单元格数据。脚注使用tab_footnote()函数添加。帮助函数cells_data()可以用于脚本靶向单元格数据的位置。cells_data()columnsrows两个选项。它们每一个都可以(1)提供一个行名或列名的向量(2)1个行索引/列索引的向量(3)包含在vars()函数中的裸列名(4)选择帮助函数starts_with()ends_with()contains()matches()one_of()everything()。针对行,我们可以使用以列名为变量的条件语句(例如size > 15000)。

这里有一个如何添加脚注的简单例子。

# 给2个不停的单元格添加脚注
gt_tbl <-
gt_tbl %>%
tab_footnote(
footnote = "The Americas.",
locations = cells_data(
columns = vars(name),
rows = 3:4)
)

# 显示
gt_tbl

下面是一个更复杂的例子

# 找到包含最大陆块的行
largest <-
islands_tbl %>%
arrange(desc(size)) %>%
slice(1) %>%
pull(name)

# 创建2个脚注
gt_tbl <-
gt_tbl %>%
tab_footnote(
footnote = md("The **largest** by area."),
locations = cells_data(
columns = vars(size),
rows = name == largest)
) %>%
tab_footnote(
footnote = "The lowest by population.",
locations = cells_data(
columns = vars(size),
rows = size == min(size))
)

# 显示
gt_tbl

这里我们使用cells_data()靶向添加脚注的单元格,其他cells_*()函数有相似的接口,可以靶向表格不同的要素。

(Stub)是表格左边包含行标签(也可以包含行标签组)、汇总标签的部分。子要素可以划分为不同的行组。根头(Stub Head)提供了描述根的标签位置。根是一个可选的要素,有时候它不是那么有用。

gt()函数中填入rowname_col参数即可生成根部分。另外,我们可以用另一个包含列名为rowname的数据集作为gt生成根部分的内容。

# 创建根
gt_tbl <-
islands_tbl %>%
gt(rowname_col = "name")

# 展示
gt_tbl

观察到左边大陆块名字没?这就是根。我们也可以使用tab_stubhead_head()为它创建标签名。

gt_tbl <-
gt_tbl %>%
tab_stubhead_label(label = "landmass")


gt_tbl

这里有一件事情非常需要注意::现在只有1列(而不是两列)。

我们把之前的要素也加上去:

gt_tbl <-
gt_tbl %>%
tab_header(
title = "Large Landmasses of the World",
subtitle = "The top ten largest are presented"
) %>%
tab_source_note(
source_note = "Source: The World Almanac and Book of Facts, 1975, page 406."
) %>%
tab_source_note(
source_note = md("Reference: McNeil, D. R. (1977) *Interactive Data Analysis*. Wiley.")
) %>%
tab_footnote(
footnote = md("The **largest** by area."),
locations = cells_data(
columns = vars(size),
rows = largest)
) %>%
tab_footnote(
footnote = "The lowest by population.",
locations = cells_data(
columns = vars(size),
rows = contains("arc"))
)

gt_tbl

接下来我们将行划分为不同的组,创建行组。这个功能通过tab_row_group()函数实现,输入包括组名和组元素。

gt_tbl <-
gt_tbl %>%
tab_row_group(
group = "continent",
rows = 1:6
) %>%
tab_row_group(
group = "country",
rows = c("Australia", "Greenland")
) %>%
tab_row_group(
group = "subregion",
rows = c("New Guinea", "Borneo")
)

# Show the gt Table
gt_tbl
#> Warning in min(rows_matched): no non-missing arguments to min; returning
#> Inf
#> Warning in max(rows_matched): no non-missing arguments to max; returning -
#> Inf

至于如何自定义组名的设定和选择,不妨发挥你们得想象力

列标签

类似于行组,使用tab_spanner()可以将多个列划分为不同的组。

# Modify the `airquality` dataset by adding the year
# of the measurements (1973) and limiting to 10 rows
airquality_m <-
airquality %>%
mutate(Year = 1973L) %>%
slice(1:10)

# Create a display table using the `airquality`
# dataset; arrange columns into groups
gt_tbl <-
gt(data = airquality_m) %>%
tab_header(
title = "New York Air Quality Measurements",
subtitle = "Daily measurements in New York City (May 1-10, 1973)"
) %>%
tab_spanner(
label = "Time",
columns = vars(Year, Month, Day)
) %>%
tab_spanner(
label = "Measurement",
columns = vars(Ozone, Solar.R, Wind, Temp)
)

# Show the gt Table
gt_tbl

我们还可以做下面两件事情

  • 使用cols_move_to_start()Time列移动到最前面
  • 使用cols_label()自定义列标签
gt_tbl <-
gt_tbl %>%
cols_move_to_start(
columns = vars(Year, Month, Day)
) %>%
cols_label(
Ozone = html("Ozone,<br>ppbV"),
Solar.R = html("Solar R.,<br>cal/m<sup>2</sup>"),
Wind = html("Wind,<br>mph"),
Temp = html("Temp,<br>&deg;F")
)

gt_tbl

还有其他的cols_*()函数帮助完成其他自定义的功能。

md()函数可以完成markdown转换,html()可以创建html支持的格式。


来源:https://gt.rstudio.com/articles/intro-creating-gt-tables.html有删改


其他相关包:

knitr (GITHUB[1], WEBSITE[2]) — kableExtra (GITHUB[3], WEBSITE[4]) — formattable (GITHUB[5], WEBSITE[6]) — DT (GITHUB[7], WEBSITE[8]) — pander (GITHUB[9], WEBSITE[10]) — huxtable (GITHUB[11], WEBSITE[12]) — reactable (GITHUB[13], WEBSITE[14]) — flextable (GITHUB[15], WEBSITE[16]) — pixiedust (GITHUB[17]) — tangram (GITHUB[18]) — ztable (GITHUB[19]) — condformat (GITHUB[20]) — stargazer (CRAN[21]) — xtable (CRAN[22])

参考资料

[1]

GITHUB: https://github.com/yihui/knitr

[2]

WEBSITE: https://yihui.org/knitr/

[3]

GITHUB: https://github.com/haozhu233/kableExtra

[4]

WEBSITE: https://haozhu233.github.io/kableExtra/

[5]

GITHUB: https://github.com/renkun-ken/formattable

[6]

WEBSITE: https://renkun-ken.github.io/formattable/

[7]

GITHUB: https://github.com/rstudio/DT

[8]

WEBSITE: https://rstudio.github.io/DT/

[9]

GITHUB: https://github.com/Rapporter/pander

[10]

WEBSITE: http://rapporter.github.io/pander

[11]

GITHUB: https://github.com/hughjonesd/huxtable

[12]

WEBSITE: https://hughjonesd.github.io/huxtable/

[13]

GITHUB: https://github.com/glin/reactable

[14]

WEBSITE: https://glin.github.io/reactable/

[15]

GITHUB: https://github.com/davidgohel/flextable

[16]

WEBSITE: https://davidgohel.github.io/flextable/

[17]

GITHUB: https://github.com/nutterb/pixiedust

[18]

GITHUB: https://github.com/spgarbet/tangram

[19]

GITHUB: https://github.com/cardiomoon/ztable

[20]

GITHUB: https://github.com/zeehio/condformat

[21]

CRAN: https://cran.r-project.org/package=stargazer

[22]

CRAN: https://cran.r-project.org/package=xtable