R语言无重复分组抽样求助:避免样本内PId重复的解决方案
解决分组抽样中样本内PId不重复的问题
问题背景
需从384行的dataframe中随机抽取24个样本,每个样本包含16条数据,且必须覆盖4个分组因子(Type、Valence、LT、Gender,各2个水平)的所有组合。要求单个样本内的PId不能重复,但原有分组抽样方法会出现同一PId在样本内重复的情况。
核心思路
每个PId对应固定的Gender,且覆盖了Type、Valence、LT的全部8种组合。因此每个样本的16条数据(对应16种因子组合)需从16个不同的PId中抽取(8个M、8个F),每个PId仅贡献其Gender下某一种Type+Valence+LT组合的条目。
方法一:组合匹配式抽样(高效稳定)
直接为每个因子组合分配不重复的PId,避免重复抽样的冗余操作:
library(tidyverse) # 预处理:按Gender和PId聚合每个被试的所有组合条目 pid_combinations <- df2 %>% group_by(Gender, PId) %>% nest() %>% ungroup() # 生成所有需要覆盖的因子组合模板 combination_template <- expand_grid( Type = c("E", "S"), Valence = c("P", "N"), LT = c("L", "T"), Gender = c("M", "F") ) set.seed(123) # 保证结果可复现 samples <- map_dfr(seq_len(24), function(sample_num) { # 分Gender处理:为每个Gender的8种组合分配8个不重复的PId sample_data <- map_dfr(c("M", "F"), function(gender) { # 筛选当前Gender的所有PId available_pids <- pid_combinations %>% filter(Gender == gender) %>% pull(PId) # 随机抽取8个不重复的PId selected_pids <- sample(available_pids, size = 8, replace = FALSE) # 为选中的PId随机分配对应的Type+Valence+LT组合 assigned_pairs <- combination_template %>% filter(Gender == gender) %>% slice_sample(n = 8) %>% mutate(PId = selected_pids) # 从原数据中匹配对应条目 df2 %>% inner_join(assigned_pairs, by = c("Gender", "PId", "Type", "Valence", "LT")) }) # 添加样本编号 sample_data %>% mutate(sample_no = sample_num) }) # 验证:每个样本的PId是否全部唯一 samples %>% group_by(sample_no) %>% summarise(unique_pid_count = n_distinct(PId)) %>% pull(unique_pid_count) %>% all(. == 16) # 返回TRUE则验证通过
方法二:循环抽样直到满足条件(直观易理解)
通过循环重复抽样,直到单个样本内的PId无重复,适合样本量较小的场景:
set.seed(123) N <- 24 df3 <- tibble() for (i in 1:N) { repeat { # 按因子组合随机抽取16条数据 candidate_sample <- df2 %>% group_by(Type, Valence, LT, Gender) %>% slice_sample(n = 1) %>% ungroup() # 检查样本内PId是否重复 if (n_distinct(candidate_sample$PId) == 16) break } # 合并样本并添加编号 df3 <- df3 %>% bind_rows(candidate_sample %>% mutate(sample_no = i)) } # 验证结果 df3 %>% group_by(sample_no) %>% summarise(n_distinct(PId)) %>% pull() %>% all(. ==16)
内容的提问来源于stack exchange,提问作者Marshal
相关产品推荐
相关产品推荐

