使用dplyr对K个不同样本量分组抽取floor(n[k]*p)样本的问题
解决分组内按不同数量抽样的问题
这问题我碰到过!确实sample_n()没法直接用,因为它要求size参数是一个全局标量,不能跟着每个分组动态变化。不过用tidyverse的工具完全能搞定,给你两种符合规范的解决方案:
方法1:用slice_sample()(推荐)
dplyr从1.0.0版本开始推荐用slice_sample()替代sample_n(),它最大的优势就是支持在分组上下文里计算抽样数量——正好满足你的需求!
假设你要按比例p抽样(比如你例子里的p=0.5对应floor(n()/2)),代码可以这么写:
library(dplyr) # 替换成你的数据框和分组列,p是抽样比例 df %>% group_by(my_group) %>% slice_sample(n = floor(n() * p)) %>% ungroup() # 按需取消分组
测试示例
我们用模拟数据验证一下:
set.seed(123) # 固定随机种子,结果可复现 df <- tibble( my_group = rep(c("A", "B", "C"), c(5, 7, 4)), # A组5个,B组7个,C组4个 value = rnorm(16) ) # 按50%比例抽样,每个组抽floor(n*0.5)个 df %>% group_by(my_group) %>% slice_sample(n = floor(n() * 0.5))
运行后你会看到:
- A组5个元素抽2个
- B组7个元素抽3个
- C组4个元素抽2个
完全符合预期!
方法2:用group_modify()
如果你习惯用更“显式”的分组处理逻辑,group_modify()也能实现。它会对每个分组的数据框单独操作:
df %>% group_by(my_group) %>% group_modify(~ slice_sample(.x, n = floor(nrow(.x) * p))) %>% ungroup()
这里.x代表每个分组的子数据框,nrow(.x)就是当前组的元素数量,逻辑和第一种方法一致,只是写法更繁琐一点。
为什么原来的代码不行?
你之前的代码sample_n(n_samples)报错,是因为sample_n()的size参数只能接受一个单一数值,不能是分组内生成的变量列。而slice_sample()允许传入一个表达式,这个表达式会在每个分组的上下文里计算,所以能动态获取每个组的抽样数量。
内容的提问来源于stack exchange,提问作者gsmafra
相关产品推荐
相关产品推荐

