You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 08:35:13