You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

R语言按组无放回采样且最终结果无重复ID_2的实现问题

原代码的问题在于分组采样是每个ID_1组独立执行,没有全局的ID_2去重约束,因此会出现同一个对照ID被分配给多个原始参与者的情况。可以通过以下几种方案调整:

方案1:基础R循环实现(逻辑直观易调试)

核心逻辑是逐个遍历ID_1,每次选择当前ID_1对应的未被使用的ID_2,选完后将该ID_2加入全局禁用池,避免后续重复选择。

library(dplyr)

# 提取所有唯一的原始参与者ID
unique_id1 <- unique(df$ID_1)
# 初始化结果存储、已使用ID池
match_result <- list()
used_id2 <- c()

for (id in unique_id1) {
  # 筛选当前ID_1可用的未被使用的对照ID
  available_id2 <- df %>%
    filter(ID_1 == id, !ID_2 %in% used_id2) %>%
    pull(ID_2)
  
  # 随机抽取1个对照ID
  selected_id2 <- sample(available_id2, size = 1)
  # 记录匹配结果
  match_result[[as.character(id)]] <- df %>%
    filter(ID_1 == id, ID_2 == selected_id2) %>%
    slice(1)
  # 更新已使用ID池
  used_id2 <- c(used_id2, selected_id2)
}

# 合并结果为数据框
final_match <- bind_rows(match_result)
  • 逻辑清晰,可随时插入打印语句调试
  • 可灵活扩展其他匹配约束,只需在filter中添加对应条件即可

方案2:tidyverse风格无循环实现

使用purrr::reduce实现迭代逻辑,无需显式写循环,代码更简洁:

library(dplyr)
library(purrr)

unique_id1 <- unique(df$ID_1)

final_match <- reduce(unique_id1, function(res, curr_id) {
  used_id2 <- res$ID_2
  curr_selected <- df %>%
    filter(ID_1 == curr_id, !ID_2 %in% used_id2) %>%
    slice_sample(n = 1) # dplyr 1.0.0+ 推荐替代sample_n的函数
  bind_rows(res, curr_selected)
}, .init = tibble())

前置检查说明

运行匹配代码前建议先做容量校验,避免因匹配池不足导致抽样失败:

# 检查每个ID_1的候选ID_2数量
df %>% group_by(ID_1) %>% summarise(candidate_cnt = n_distinct(ID_2))
# 全局校验:唯一对照ID总数必须大于等于原始参与者ID总数,才有可能实现无重复匹配
n_distinct(df$ID_2) >= n_distinct(df$ID_1)

内容的提问来源于stack exchange,提问作者George

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 07:09:00