如何在分组内抽样type 0以匹配对应组type 1的样本量?
问题描述
我拥有一个极不平衡的数据集,包含多个组,每组被划分为两类观测值。以下是结构的合成示例(实际数据包含数百个组和数百万条观测值):
df <- data.frame( group = c(1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2), type = c(0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1), value = c(1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 8, 9) )
我需要比较每组内各type的标准差,类似如下代码逻辑:
df %>% group_by(group, type) %>% ## 此处需添加抽样逻辑... summarise(n = n(), mean = mean(value))
但两类观测值的数量不平衡,这会导致比较结果存在偏差。我计划通过抽样减少type 0的观测值数量,使其匹配每组对应type 1的观测值数量。我了解到可使用slice_sample(),但无法在这种分组-类型匹配的场景下正确运用,请问如何从每组的group+type0观测池中抽样,以匹配对应组group+type1观测池的大小?
解决方案
可以通过先计算每组type1的样本量,再基于该数量对同组的type0进行抽样,具体实现有两种高效思路:
方法1:先统计样本量再关联抽样
library(dplyr) # 先计算每组type1的观测数量 type1_counts <- df %>% filter(type == 1) %>% group_by(group) %>% summarise(n_type1 = n()) # 对type0进行抽样,匹配对应组type1的数量,同时保留所有type1数据 sampled_df <- df %>% left_join(type1_counts, by = "group") %>% group_by(group, type) %>% # 仅对type0执行抽样,type1保留全部 slice_sample(n = ifelse(type == 0, first(n_type1), n())) %>% ungroup() %>% select(-n_type1) # 移除临时统计列 # 执行后续统计分析 sampled_df %>% group_by(group, type) %>% summarise( n = n(), mean = mean(value), sd = sd(value) )
方法2:分组内直接匹配样本量
这种方法无需额外关联表,直接在分组内完成逻辑处理,内存效率更高:
library(dplyr) sampled_df <- df %>% group_by(group) %>% # 获取当前组type1的样本量 mutate(n_type1 = sum(type == 1)) %>% group_by(group, type, .add = TRUE) %>% # 对type0抽样到同组type1的数量,type1保留全部 slice_sample(n = ifelse(type == 0, first(n_type1), n())) %>% ungroup() %>% select(-n_type1) # 执行后续统计分析 sampled_df %>% group_by(group, type) %>% summarise( n = n(), mean = mean(value), sd = sd(value) )
关键说明
- 两种方法都确保每组的type0样本量与同组type1完全一致,彻底解决数据不平衡带来的偏差问题
slice_sample()的n参数支持条件判断,仅对type0执行抽样操作,type1数据完整保留- 处理百万级数据时,方法2的性能更优,无需额外创建中间统计表
内容的提问来源于stack exchange,提问作者BoTz
相关产品推荐
相关产品推荐

