如何用tidyverse简化嵌套数据框生成多列表列的代码?求抽样资源
问题描述
需要从嵌套数据框的数据列创建多个列表列,现有R代码功能可行但过于冗长,希望借助tidyverse工具(dplyr、purrr等)简化(非嵌套数据框中常用across()),最终目标是利用生成的经验分布进行随机抽样,同时需要相关参考资源。
现有冗长代码:
# R version 3.6.1 library(dplyr) # 1.0.7 library(tidyr) # 1.2.0 df_distribution <- iris %>% dplyr::group_by(Species) %>% tidyr::nest() %>% dplyr::mutate(Sepal.Length = purrr::map(data, ~ dplyr::select(.x, Sepal.Length) %>% dplyr::group_by(Sepal.Length) %>% dplyr::summarise(n = n() ) %>% dplyr::mutate(perc = n / sum(n) ) %>% dplyr::select(-n) ) ) %>% dplyr::mutate(Sepal.Width = purrr::map(data, ~ dplyr::select(.x, Sepal.Width) %>% dplyr::group_by(Sepal.Width) %>% dplyr::summarise(n = n() ) %>% dplyr::mutate(perc = n / sum(n) ) %>% dplyr::select(-n) ) ) %>% dplyr::mutate(Petal.Length = purrr::map(data, ~ dplyr::select(.x, Petal.Length) %>% dplyr::group_by(Petal.Length) %>% dplyr::summarise(n = n() ) %>% dplyr::mutate(perc = n / sum(n) ) %>% dplyr::select(-n) ) ) %>% dplyr::mutate(Petal.Width = purrr::map(data, ~ dplyr::select(.x, Petal.Width) %>% dplyr::group_by(Petal.Width) %>% dplyr::summarise(n = n() ) %>% dplyr::mutate(perc = n / sum(n) ) %>% dplyr::select(-n) ) )
简化代码方案
可以利用across()配合purrr::map,直接遍历所有目标列,省去重复的mutate调用,逻辑和非嵌套数据框的across用法一致:
library(dplyr) library(tidyr) library(purrr) # 定义要处理的数值列 target_cols <- names(iris)[-5] df_distribution <- iris %>% group_by(Species) %>% nest() %>% # 用across遍历所有目标列,对每个列用map处理嵌套数据框 mutate(across(all_of(target_cols), ~ map(data, function(col_data) { col_data %>% select(!!sym(cur_column())) %>% group_by(!!sym(cur_column())) %>% summarise(perc = n() / n(), .groups = "drop") }))) %>% select(-data) # 移除原始嵌套数据列
如果需要更高效的长格式中转处理,也可以用以下方式,先统一计算所有列的分布再转回宽格式列表列:
df_distribution <- iris %>% group_by(Species) %>% nest() %>% mutate( dist_long = map(data, ~ .x %>% pivot_longer(everything(), names_to = "var", values_to = "value") %>% group_by(var, value) %>% summarise(perc = n() / n(), .groups = "drop")), # 将长格式分布拆分为各列的列表列 !!!map(target_cols, ~ sym(.x) := map(dist_long, ~ filter(.x, var == .y) %>% select(-var), .y = .x)) ) %>% select(-data, -dist_long)
经验分布抽样相关参考资源
- tidyverse官方文档:
dplyr::sample_n/dplyr::sample_frac支持按权重抽样,结合purrr::map可应用到每个列表列的经验分布;tidyr::unnest可展开分布数据后完成抽样操作。 - 《R语言实战(第二版)》:第11章抽样与重抽样章节,覆盖经验分布抽样的基础方法与实践案例。
- purrr包官方教程:嵌套数据处理章节详细讲解了
map系列函数对嵌套结构的操作,是处理这类问题的核心工具。 - 《统计建模与R语言》:书中关于经验分布与Bootstrap抽样的内容,可帮助理解基于经验分布实现随机抽样的底层逻辑。
内容的提问来源于stack exchange,提问作者MatSchu
相关产品推荐
相关产品推荐

