使用R或tidyverse调整数据框比例匹配已知参数的实现
用For循环调整数据分布匹配目标比例
完全可以用for循环实现数据裁剪,让最终样本的性别、教育水平分布匹配指定比例。下面是具体实现步骤和代码:
1. 修正测试数据(避免原代码的行数不匹配问题)
原测试数据的sex和schooling行数不一致,先调整为可正常使用的随机数据:
set.seed(123) # 设置随机种子,保证结果可重复 df2 <- data.frame( sex = sample(c("m","f"), size = 300, replace = TRUE), schooling = sample(c("elementary","highschool","college"), size = 300, replace = TRUE) ) # 查看当前数据的分布比例 prop.table(table(df2$sex)) prop.table(table(df2$schooling))
2. 定义目标分布比例
# 性别目标比例:女性(f)70%,男性(m)30% target_sex <- c("f" = 0.7, "m" = 0.3) # 教育水平目标比例:小学50%,高中30%,大学20% target_school <- c("elementary" = 0.5, "highschool" = 0.3, "college" = 0.2)
3. 计算可保留的最大样本量
为了保证每个分组都能抽取到目标数量的样本,先计算当前数据能支持的最大最终样本量:
# 按性别计算最大可支撑样本量 max_n_sex <- min( sum(df2$sex == "f") / target_sex["f"], sum(df2$sex == "m") / target_sex["m"] ) # 按教育水平计算最大可支撑样本量 max_n_school <- min( sum(df2$schooling == "elementary") / target_school["elementary"], sum(df2$schooling == "highschool") / target_school["highschool"], sum(df2$schooling == "college") / target_school["college"] ) # 取两者的较小值作为最终样本量(向下取整) final_n <- floor(min(max_n_sex, max_n_school))
4. For循环实现分组抽样
通过循环遍历每个性别-教育水平的交叉分组,抽取对应数量的样本:
# 生成所有交叉分组的目标数量表 target_counts <- expand.grid(sex = names(target_sex), schooling = names(target_school)) target_counts$proportion <- target_sex[target_counts$sex] * target_school[target_counts$schooling] target_counts$target_n <- floor(final_n * target_counts$proportion) # 初始化空数据框存储调整后的数据 adjusted_df <- data.frame() # 循环抽取每个分组的样本 for(i in 1:nrow(target_counts)){ # 筛选当前分组的原始数据 current_group <- df2[df2$sex == target_counts$sex[i] & df2$schooling == target_counts$schooling[i], ] # 抽取目标数量的样本(如果现有样本足够) if(nrow(current_group) >= target_counts$target_n[i]){ sampled_rows <- sample(nrow(current_group), size = target_counts$target_n[i], replace = FALSE) adjusted_df <- rbind(adjusted_df, current_group[sampled_rows, ]) } else { # 若现有样本不足,则全部保留(理论上不会出现,因为已提前计算final_n) adjusted_df <- rbind(adjusted_df, current_group) } }
5. 验证调整后的分布
运行以下代码查看最终数据的比例是否符合要求:
prop.table(table(adjusted_df$sex)) prop.table(table(adjusted_df$schooling))
关键说明
- 采用交叉分组抽样的方式,能同时保证性别和教育水平的分布都匹配目标比例,避免单一维度调整后破坏另一维度的比例
- 设置
set.seed()可以让抽样结果可重复,方便后续验证
内容的提问来源于stack exchange,提问作者Luis
相关产品推荐
相关产品推荐

