R中无放回随机抽样避错:按条件抽取5%行的实现问题
问题解决:分组随机抽样报错处理
需求
- 按
speaker和lang过滤数据后,对每个child_id分组做无放回抽样:- 若分组行数≤4,直接跳过该分组;
- 若分组行数≥5,抽取该分组行数的5%(至少1行);
- 最终汇总所有抽取的行组成表格。
报错信息
Error in `sample_n()`: ! Can't compute indices. ℹ In group 1: `child_id = 112`. Caused by error: ! `size` must be less than or equal to 159 (size of data). ℹ set `replace = TRUE` to use sampling with replacement.
原代码
set.seed(123) random_all_speakers_10 <- data.frame() speakers <- c("Mom", "Dad", "Other", "Multiple") languages <- c("Fr", "Eng") for (speaker in speakers) { for (lang in languages) { filtered_data <- data_10_coded_collapsed %>% filter(spkr == speaker, lang == lang) if (nrow(filtered_data) > 4) { num_to_sample <- max(1, round(nrow(filtered_data) * 0.05)) if (num_to_sample >= nrow(filtered_data)) { sampled_data <- filtered_data } else { sampled_data <- filtered_data %>% group_by(child_id) %>% sample_n(size = num_to_sample, replace = FALSE) } random_all_speakers_10 <- bind_rows(random_all_speakers_10, sampled_data) } } }
问题原因
原代码核心错误:用整个过滤后数据集的行数计算抽样数量,强制每个child_id分组都抽取该固定数量。当某个分组的行数小于这个全局抽样数时,无放回抽样无法执行,直接触发报错。
比如:整个filtered_data有3180行,计算出num_to_sample=159,但某个child_id分组只有100行,此时要求抽取159行超出了分组行数上限。
修正后的代码
set.seed(123) random_all_speakers_10 <- data.frame() speakers <- c("Mom", "Dad", "Other", "Multiple") languages <- c("Fr", "Eng") for (speaker in speakers) { for (lang in languages) { filtered_data <- data_10_coded_collapsed %>% filter(spkr == speaker, lang == lang) if (nrow(filtered_data) > 4) { sampled_data <- filtered_data %>% group_by(child_id) %>% filter(n() > 4) %>% # 跳过行数≤4的分组 slice_sample(n = max(1, round(n() * 0.05)), replace = FALSE) %>% # 每个分组单独计算抽样数 ungroup() random_all_speakers_10 <- bind_rows(random_all_speakers_10, sampled_data) } } }
关键改动说明
- 移除全局抽样数计算:改为在每个
child_id分组内,用n()获取当前分组行数,单独计算抽样数量; - 提前过滤无效分组:通过
filter(n() > 4)直接筛掉行数不足5的分组,符合需求中的跳过规则; - 使用
slice_sample替代sample_n:sample_n已被官方弃用,slice_sample是更推荐的抽样函数,语法更清晰; - 保证抽样合理性:
max(1, round(n() * 0.05))确保每个有效分组至少抽取1行,且抽样数不会超过分组行数。
内容的提问来源于stack exchange,提问作者Library_troll
相关产品推荐
相关产品推荐

