R语言基于性别、年龄两类人口变量重采样使样本匹配总体分布
R多阶段抽样样本匹配人口学分布实现方案
需求说明
多阶段抽样得到的数据集存在抽样偏差,需要调整数据使其匹配性别、年龄两个因子类型人口学变量的总体分布,要求每个年龄组内部男女性别占比为50%/50%。
样本原始分布如下图:
示例数据集
x<-structure(list(age_cat = c("25-29", "30-34", "25-29", "20-24", "25-29", "20-24", "35-39", "30-34", "25-29", "30-34", "25-29", "30-34", "35-39", "45-49", "40-45", "20-24", "20-24", "25-29", "35-39", "35-39", "25-29", "20-24", "30-34", "30-34", "40-45", "25-29", "25-29", "25-29", "20-24", "40-45", "20-24", "40-45", "30-34", "25-29", "45-49", "30-34", "45-49", "40-45", "25-29", "35-39", "40-45", "25-29", "45-49", "35-39", "45-49", "40-45", "20-24", "45-49", "40-45", "25-29", "35-39", "30-34", "30-34", "25-29", "20-24", "20-24", "40-45", "35-39", "25-29", "25-29", "20-24", "40-45", "20-24", "20-24", "45-49", "20-24", "35-39", "20-24", "35-39", "45-49", "15-19", "45-49", "35-39", "35-39", "30-34", "35-39", "45-49", "35-39", "30-34", "20-24", "35-39", "40-45", "40-45", "40-45", "30-34", "45-49", "20-24", "30-34", "45-49", "35-39", "20-24", "20-24", "20-24", "45-49", "20-24", "45-49", "35-39", "25-29", "40-45", "40-45", "25-29", "35-39", "45-49", "30-34", "45-49", "45-49", "45-49", "15-19", "30-34", "45-49", "30-34", "30-34", "35-39", "25-29", "40-45", "15-19", "20-24", "20-24", "40-45", "40-45", "45-49", "45-49", "35-39", "40-45", "30-34", "35-39", "35-39", "25-29", "25-29", "20-24", "20-24", "40-45", "20-24", "35-39", "20-24", "20-24", "30-34", "25-29", "45-49", "25-29", "35-39", "20-24", "35-39", "35-39", "35-39", "40-45", "35-39", "35-39", "20-24", "30-34", "25-29", "15-19", "30-34", "35-39", "15-19", "20-24", "20-24", "35-39", "25-29", "25-29", "25-29", "25-29", "30-34", "40-45", "35-39", "30-34", "35-39", "40-45", "25-29", "30-34", "25-29", "25-29", "45-49", "30-34", "30-34", "25-29", "15-19", "25-29", "20-24", "15-19", "20-24", "30-34", "20-24", "40-45", "25-29", "25-29", "30-34", "30-34", "25-29", "20-24", "40-45", "45-49", "25-29", "25-29", "40-45", "35-39", "25-29", "45-49", "35-39", "30-34", "45-49", "30-34", "30-34", "45-49", "35-39", "20-24", "45-49", "30-34", "25-29", "45-49", "45-49", "40-45", "25-29", "20-24", "40-45", "30-34", "35-39", "30-34", "20-24", "35-39", "20-24", "30-34", "20-24", "35-39", "35-39", "30-34", "45-49", "40-45", "45-49", "25-29", "35-39", "40-45", "30-34", "35-39", "30-34", "35-39", "20-24", "25-29", "35-39", "30-34", "30-34", "25-29", "45-49", "45-49", "40-45", "40-45", "35-39", "30-34", "25-29", "35-39", "20-24", "40-45", "20-24", "30-34", "40-45", "20-24", "45-49", "20-24", "40-45", "25-29", "40-45", "25-29", "45-49", "30-34", "30-34", "45-49", "40-45", "30-34", "30-34", "20-24", "20-24", "35-39", "30-34", "15-19", "35-39", "25-29", "45-49", "30-34", "25-29", "35-39", "15-19", "40-45", "45-49", "15-19", "35-39", "45-49", "45-49", "25-29"), sex_cat = structure(c(1L, 2L, 1L, 2L, 1L, 1L, 1L, 2L, 2L, 1L, 1L, 2L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 2L, 2L, 2L, 1L, 2L, 2L, 1L, 2L, 2L, 2L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 1L, 1L, 2L, 2L, 1L, 1L, 2L, 2L, 2L, 1L, 2L, 1L, 1L, 2L, 2L, 1L, 2L, 2L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 2L, 1L, 2L, 2L, 1L, 2L, 1L, 1L, 1L, 2L, 2L, 1L, 1L, 2L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 1L, 2L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 2L, 1L, 1L, 2L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 2L, 2L, 1L, 1L, 1L, 1L, 2L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 2L, 2L, 1L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 2L, 2L, 1L, 2L, 1L, 2L, 1L, 1L, 2L, 2L, 1L, 2L, 1L, 1L, 1L, 1L, 2L, 2L, 1L, 1L, 1L, 2L, 1L, 2L, 1L, 1L, 2L, 1L, 2L, 2L, 2L, 1L, 2L, 2L, 2L, 1L, 2L, 1L, 2L, 1L, 1L, 2L, 1L, 2L, 1L, 1L, 1L, 1L, 2L, 2L, 1L, 2L, 1L, 1L, 2L, 1L, 2L, 1L, 1L, 1L, 2L, 2L, 1L, 1L, 1L, 2L, 1L, 2L, 2L, 1L, 1L, 2L, 1L, 2L, 1L, 2L, 2L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 1L, 1L, 2L, 1L, 2L, 2L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 2L, 2L, 2L, 1L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 1L, 2L, 1L, 1L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = c("M", "F"), class = "factor")), row.names = c(NA, -288L), class = c("tbl_df", "tbl", "data.frame"))
实现方法
不需要手动编写循环,两种成熟方案可直接满足需求:
方案1:后分层加权(保留全部原始样本)
适合不需要调整样本量,仅通过权重校正分布的场景:
library(survey) library(dplyr) # 构造目标分布:每个年龄组男女占比各50% age_total <- x %>% count(age_cat, name = "total") pop_dist <- expand.grid(age_cat = unique(x$age_cat), sex_cat = c("M", "F")) %>% left_join(age_total, by = "age_cat") %>% mutate(Freq = total / 2) %>% select(age_cat, sex_cat, Freq) # 定义调查设计并执行后分层加权 base_des <- svydesign(id = ~1, data = x, weights = ~1) post_des <- postStratify(base_des, strata = ~age_cat + sex_cat, population = pop_dist) # 提取带权重的结果数据集 weighted_data <- post_des$variables %>% mutate(weight = weights(post_des))
后续分析直接使用weight列作为样本权重即可,加权后每个年龄组的性别占比完全符合50%/50%的要求。
方案2:分层重抽样(调整样本量得到完全匹配的数据集)
如果需要得到实际样本分布匹配目标要求的数据集,直接按组抽样即可:
library(dplyr) adjusted_data <- x %>% # 按年龄分组,确定每组可抽取的男女最大等量子样量 group_by(age_cat) %>% mutate(sample_n = min(table(sex_cat))) %>% # 按年龄+性别分组抽样 group_by(age_cat, sex_cat) %>% slice_sample(n = first(sample_n)) %>% ungroup() %>% select(-sample_n)
执行后可通过adjusted_data %>% count(age_cat, sex_cat)验证结果,每个年龄组的男女样本量完全相等。
内容的提问来源于stack exchange,提问作者Luis
相关产品推荐
相关产品推荐

