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

使用dplyr实现带最小样本量约束的分层比例分配抽样

实现带最小样本约束的比例分配分层抽样(dplyr版)

要实现你需求的「比例分配抽样+每个层至少抽1个样本」,我们可以把计算逻辑和抽样步骤整合到dplyr的管道操作里,一步到位。下面是完整的解决方案:

完整代码示例

library(dplyr)
set.seed(123) # 设置随机种子,确保结果可重复

# 构造你的原始数据
var = c(rep("A",10),rep("B",10),rep("C",3),rep("D",5),"E","F")
value = rnorm(30)
dat = tibble(var, value)

# 执行带约束的比例分配抽样
sampled_dat <- dat %>%
  group_by(var) %>%
  # 1. 计算每个层的大小、权重,以及目标样本量
  mutate(
    ni = n(), # 当前层的总体数量
    weight = ni / nrow(dat), # 层权重(ni/总总体量)
    target_sample = pmax(ni * weight, 1) %>% round() # 计算目标样本量,小于1则设为1,再转整数
  ) %>%
  # 2. 按调整后的目标样本量在每层抽样
  slice_sample(n = first(target_sample)) %>%
  # 3. 清理结果,保留需要的列并取消分组
  ungroup() %>%
  select(var, value)

# 查看抽样结果
sampled_dat

代码分步解释

  1. 分组与基础计算:

    • group_by(var):按你的层变量var分组,针对每个层单独处理。
    • ni = n():获取当前层的总体数量。
    • weight = ni / nrow(dat):计算每个层的权重(层大小/总体总量),这是比例分配的核心依据。
  2. 目标样本量调整:

    • pmax(ni * weight, 1):用pmax函数确保计算出的样本量(ni * weight)如果小于1,就自动替换为1,满足你「至少抽1个样本」的约束。
    • %>% round():把计算出的非整数样本量转为整数(毕竟抽样数量必须是整数;如果需要向上取整可以用ceiling,向下取整用floor,根据你的需求调整即可)。
  3. 抽样与结果清理:

    • slice_sample(n = first(target_sample)):dplyr的slice_sample专门用于抽样,这里取每个组的第一个target_sample值(因为同组内该值都相同)作为抽样数量。
    • ungroup():可选操作,取消分组让结果更整洁;select(var, value)保留你需要的列,去掉中间计算的辅助列。

抽样结果验证

按照你的数据结构,最终每个层的抽样数量会是:

  • A层:3个(10*(10/30)≈3.33,取整为3)
  • B层:3个(同A层)
  • C层:1个(3*(3/30)=0.3,触发最小样本约束)
  • D层:1个(5*(5/30)≈0.83,触发最小样本约束)
  • E/F层:各1个(都触发最小样本约束)

这样既满足了比例分配的要求,又保证了小层不会被遗漏。

内容的提问来源于stack exchange,提问作者Homer Jay Simpson

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 23:29:07