count()
计算出各种 cut
的钻石各有多少个,存到名为 n
的列里,然后通过 mutate 计算出总和为1的占比。此时如果用 geom_col()
画图可以得出一个高度为1的堆积图。library(tidyverse)
diamonds %>%
count(cut) %>%
mutate(p = n / sum(n)) %>%
ggplot(aes("", p, fill = cut)) +
geom_col() +
scale_fill_brewer(type = "div")
再加以 coord_polar()
变换转换为极座标,就可以画出一张饼图了。在此基础上多叠加一层 geom_text()
就实现了百分比的显示,非常灵活。
diamonds %>%
count(cut) %>%
mutate(p = n / sum(n)) %>%
mutate(labels = scales::label_percent(accuracy = 0.01)(n / sum(n))) %>%
ggplot(aes("", p, fill = cut)) +
geom_col() +
geom_text(aes(label = labels), position = position_stack(0.5)) +
coord_polar("y") +
scale_fill_brewer(type = "div")
如果不想显示极座标轴和灰色背景,可以通过加上 theme_void()
来实现。对于重叠的文字则是可以用 ggrepel 打散,最终效果如图。
unnest()
系列函数,可以用于展开嵌套的数据结构。配合 fromJSON()
使用就可以实现 JSON 字段的展开。library(tidyverse)
library(jsonlite)
spread_all <- function(data, cols) {
data %>%
mutate(across(all_of(cols), function(x)
map(x, fromJSON))) %>%
unnest_wider(all_of(cols))
}
# 用法
df %>%
spread_all(c("x", "y"))
为了加速 JSON 的解析,我们可以引入 furrr
包来实现并发解析。
library(furrr)
# make future_map parallel
plan(multisession)
spread_all <- function(data, cols) {
data %>%
mutate(across(all_of(cols), function(x)
future_map(x, fromJSON))) %>%
unnest_wider(all_of(cols))
}
]]>read_csv()
分别读取每个文件,再用 reduce(rbind)
聚合到一起。这样确实能用,但对于大数据集来说性能很差。readr 从 2.0.0 开始原生支持同时读取多个文件的功能,只需要把文件名字符串向量里传给 file 参数就行。实测在数据量很大的时候和 rbind 相比可以显著减少读取时间。这个功能在 readr 包的文档中没有描述,导致我走了不少弯路才发现 readr 原生就支持多文件读取。
另外 vroom 从 1.0.0 开始就原生支持了这个功能,用法一样不过 vroom 对于文件中的字符数据是懒加载的,在某些场景下可以提升性能。具体能否提升性能要看使用方式了,可以用 system.time({})
实测一下。