You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 16:47:36