在R语言中进行分层抽样时,如何指定目标总样本量?
解决方案:自动化分层抽样保留组合频率
我来帮你搞定这个自动化分层抽样的需求!你想要从5万次模拟的数据集中抽取1万次模拟,同时保留SCENARIO ID-TARGET ID组合的频率分布,之前用splitstackshape::stratified只能手动指定每组样本量,确实不够灵活。下面是一个全自动化的R实现方案,用dplyr和purrr就能搞定:
核心思路
我们的目标是让抽样后的1万次模拟中,每个SCENARIO ID-TARGET ID组合的出现频率和原数据集尽可能一致。具体步骤是:
- 统计原数据中每个组合对应的模拟数量及占比
- 根据总目标抽样数(1万)自动计算每个组合需要抽取的模拟数
- 按计算结果抽取模拟,最后调整数量确保刚好是1万次模拟
代码实现
假设你的数据集叫df,包含SIMULATION、SCENARIO ID、TARGET ID三列:
library(dplyr) library(purrr) # 1. 统计每个组合对应的所有唯一模拟,以及该组合的总模拟数 comb_sim_data <- df %>% distinct(SIMULATION, `SCENARIO ID`, `TARGET ID`) %>% group_by(`SCENARIO ID`, `TARGET ID`) %>% summarise(simulation_list = list(SIMULATION), .groups = "drop") %>% mutate(total_sim_count = length(simulation_list)) # 2. 计算每个组合的抽样比例和目标抽取数 total_original_sim <- length(unique(df$SIMULATION)) # 原模拟总数:50000 target_sim_count <- 10000 # 目标抽样数 comb_sim_data <- comb_sim_data %>% mutate( sim_proportion = total_sim_count / total_original_sim, target_sim = round(sim_proportion * target_sim_count) ) # 3. 处理四舍五入后的总数偏差(确保总抽样数刚好是10000) count_diff <- target_sim_count - sum(comb_sim_data$target_sim) if (count_diff != 0) { # 给模拟数最多的组合调整数量(补/减) comb_sim_data <- comb_sim_data %>% arrange(desc(total_sim_count)) %>% mutate(target_sim = target_sim + c(rep(sign(count_diff), abs(count_diff)), rep(0, n() - abs(count_diff)))) %>% arrange(`SCENARIO ID`, `TARGET ID`) } # 4. 按每个组合的目标数抽取模拟 sampled_sims <- comb_sim_data %>% pmap(function(`SCENARIO ID`, `TARGET ID`, simulation_list, target_sim, ...) { sample(simulation_list, size = target_sim, replace = FALSE) }) %>% unlist() %>% unique() # 5. 最终调整:确保抽样的模拟数刚好是10000 if (length(sampled_sims) > target_sim_count) { sampled_sims <- sample(sampled_sims, size = target_sim_count, replace = FALSE) } else if (length(sampled_sims) < target_sim_count) { remaining_sims <- setdiff(unique(df$SIMULATION), sampled_sims) sampled_sims <- c(sampled_sims, sample(remaining_sims, size = target_sim_count - length(sampled_sims), replace = FALSE)) } # 6. 从原数据中提取最终抽样的所有行 final_sampled_data <- df %>% filter(SIMULATION %in% sampled_sims)
效果说明
- 这个流程完全自动化,不需要手动调整比例
- 通过按组合的模拟占比分配抽样数量,最大程度保留了原数据中
SCENARIO ID-TARGET ID组合的频率分布 - 最后的调整步骤确保你刚好得到1万次模拟的样本
内容的提问来源于stack exchange,提问作者Bemused
相关产品推荐
相关产品推荐

