R语言dplyr包实现大数据框按组比例分配抽样及约束设置
R实现精确按组比例分配抽样
你之前的代码用全局slice_sample加权抽样属于概率抽样,无法保证每个组恰好抽到预设的Ni数量,也容易遗漏样本量极小的分组。要实现精确匹配分组抽样量、覆盖全部分组,直接按组嵌套抽样即可,具体实现如下:
1. 数据准备与样本量计算
首先加载依赖、构造示例数据,同时实现Ni=0时强制抽1个的规则:
library(tidyverse) # 构造示例数据集 var = c(rep("a",440), rep("b",255) ,rep("c",333),rep("d",47) ,rep("e",159),rep("f",67) ,rep("g",133), rep("h",342), rep("i",131) ,rep("j",606),rep("k",129),rep("l",126),rep("m",155),rep("n",62), rep("o",616), rep("p", 173),rep("q",430),rep("r",2) ,rep("s",453), rep("t",154), rep("v",145),rep("u", 307),rep("w",233),rep("x",315),rep("y",65),rep("z",159), rep("aa",758),rep("ab",307),rep("ac", 413),rep("ad",184),rep("ae",334),rep("af",111),rep("ag",175), rep("ah", 262),rep("ai",309),rep("aj",71),rep("ak",35),rep("al",302), rep("am",266), rep("an",36),rep("ao",47),rep("ap",415),rep("aq",204),rep("ar",259)) value = rnorm(10525) dat = tibble(var,value) # 计算各组目标抽样量 sample_plan <- dat %>% group_by(var) %>% summarise( group_total = n(), # 组内总观测数 group_weight = group_total/nrow(.), # 组占总样本权重 target_n = round(group_total * group_weight) # 比例分配初始抽样量 ) %>% # 约束规则:计算得到的抽样量为0时,强制抽1个 mutate(target_n = ifelse(target_n == 0, 1, target_n))
补充:如果存在极小样本组出现「目标抽样量大于组内总观测数」的情况,可以把规则改为
target_n = pmin(group_total, ifelse(target_n == 0, 1, target_n)),避免抽样时报错。
2. 按组精确抽样
核心逻辑是分组后在组内独立抽样,从根源上保证每个组都被抽到、且抽样量完全匹配预设值:
set.seed(1234) # 设置随机种子,保证结果可复现 result_sample <- dat %>% left_join(sample_plan, by = "var") %>% group_by(var) %>% # 组内无放回抽取对应数量样本,first()取组内统一的target_n值 slice_sample(n = first(target_n), replace = FALSE) %>% ungroup()
3. 结果校验
抽样完成后可以做三层校验,确保结果符合要求:
# 统计实际抽样情况 check_res <- result_sample %>% group_by(var) %>% summarise(actual_n = n()) %>% left_join(sample_plan %>% select(var, target_n), by = "var") %>% mutate(is_match = actual_n == target_n) # 校验1:是否覆盖全部44个分组 nrow(check_res) # 返回44即为覆盖全部分组 # 校验2:所有组实际抽样量是否和目标Ni完全一致 all(check_res$is_match) # 返回TRUE即为完全匹配 # 校验3:总样本量是否符合预期 sum(check_res$actual_n) # 返回值和sum(sample_plan$target_n)完全相等
以你提供的示例数据为例,r组仅2条观测,原始计算得到的Ni为0,应用强制规则后target_n变为1,最终总样本量为355,且44个组全部被覆盖。
内容的提问来源于stack exchange,提问作者Homer Jay Simpson
相关产品推荐
相关产品推荐

