如何用dplyr的summarise实现分组数据框的条件抽样(无需拆分)
分组抽样:无需拆分数据的高效实现
核心思路
无需将数据拆分为列表再迭代,直接利用dplyr的分组向量化操作,结合slice_sample按组计算抽样数量并完成抽样。抽样数量取组内行数×抽样比例和最小抽样数中的较大值。
代码实现
library(dplyr) # 构造示例数据 set.seed(123) # 固定随机种子保证结果可复现 df <- tibble( group_id = rep(c("A", "B", "C"), c(30, 8, 4)), # 三个组,行数分别为30、8、4 value = rnorm(42) ) # 定义抽样参数 sample_ratio <- 0.1 # 抽样比例 min_sample_size <- 5 # 最小抽样数 # 高效分组抽样 sampled_data <- df %>% group_by(group_id) %>% # 按组计算抽样数量:取比例抽样数和最小抽样数的较大值 slice_sample(n = max(round(n() * sample_ratio), min_sample_size), replace = FALSE) %>% ungroup()
关键细节说明
n()的作用:在group_by的上下文里,n()直接返回当前组的行数,无需额外调用cur_data()或cur_group(),避免了作用域冲突。slice_sample的优势:该函数支持在分组后动态传入抽样数量的表达式,内部基于向量化逻辑处理,比拆分列表后用map/lapply迭代效率更高,尤其适合大数据集。- 如果仅需计算抽样数量:若不需要抽样后的行数据,仅需统计每个组的抽样规模,可使用
summarise:
sample_size_stats <- df %>% group_by(group_id) %>% summarise( required_sample_size = max(round(n() * sample_ratio), min_sample_size), .groups = "drop" )
替代方案(复杂场景)
如果需要对组内数据做更复杂的自定义处理,可使用group_modify结合cur_data():
sampled_data_custom <- df %>% group_by(group_id) %>% group_modify(function(group_data, group_keys) { n_needed <- max(round(nrow(group_data) * sample_ratio), min_sample_size) slice_sample(group_data, n = n_needed) }) %>% ungroup()
内容的提问来源于stack exchange,提问作者socialscientist
相关产品推荐
相关产品推荐

