R语言中如何基于data1的分层特征从data2抽取代表性样本?
按data1特征组合频率从data2分层抽样的解决方案
我来帮你搞定这个问题——其实用dplyr就能实现需求,可能之前你没把频数统计和分组抽样的步骤衔接好。下面是具体的可复用方法,分两步走:
第一步:统计data1中各特征组合的出现频率
首先我们需要从data1里提取所有非ID的因子特征,统计每个特征组合的出现次数:
library(dplyr) # 生成特征组合-频数对照表 freq_table <- data1 %>% select(-ID) %>% # 移除ID列,只保留因子特征 group_by(across(everything())) %>% # 按所有因子特征分组(自动适配任意数量的特征) summarise(sample_count = n(), .groups = "drop") # 计算每组的样本数,并取消分组
这段代码会生成一个表,每一行对应一个特征组合(比如Region:AA、Age:20、Label:0),并附带该组合在data1中的出现次数sample_count。
第二步:从data2中按对应数量抽样
接下来我们把这个频数表和data2关联,然后按每个特征组合抽取对应数量的样本:
# 从data2中抽取匹配样本(保留ID列) sampled_data <- data2 %>% # 关联频数表,把对应组合的抽样数量带到data2里 left_join(freq_table, by = names(freq_table)[-ncol(freq_table)]) %>% # 再次按特征组合分组 group_by(across(all_of(names(freq_table)[-ncol(freq_table)]))) %>% # 抽取对应数量的样本:first(sample_count)取该组需要的抽样数 slice_sample(n = first(sample_count), replace = FALSE) %>% ungroup() %>% select(-sample_count) # 移除临时的频数列,恢复原数据结构
特殊情况处理
如果data2中某个特征组合的样本数量少于data1中的频数(比如data1要抽6条,但data2只有4条),上面的代码会报错。你可以调整抽样逻辑,比如抽取现有所有样本,或者允许放回抽样:
情况1:抽取现有最大数量(不放回)
sampled_data_safe <- data2 %>% left_join(freq_table, by = names(freq_table)[-ncol(freq_table)]) %>% group_by(across(all_of(names(freq_table)[-ncol(freq_table)]))) %>% slice_sample(n = min(first(sample_count), n()), replace = FALSE) %>% ungroup() %>% select(-sample_count)
情况2:允许放回抽样(凑够需要的数量)
sampled_data_replace <- data2 %>% left_join(freq_table, by = names(freq_table)[-ncol(freq_table)]) %>% group_by(across(all_of(names(freq_table)[-ncol(freq_table)]))) %>% slice_sample(n = first(sample_count), replace = TRUE) %>% ungroup() %>% select(-sample_count)
补充说明
- 如果你的dplyr版本低于1.0.0,
slice_sample函数不存在,可以用sample_n(first(sample_count), replace = FALSE)替代,功能完全一致。 group_by(across(everything()))是关键,它会自动把所有非ID的因子特征作为分组依据,不管你有3个还是10个特征,都不用手动列出来,非常灵活。
内容的提问来源于stack exchange,提问作者JJR
相关产品推荐
相关产品推荐

