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

如何在R中对多观测行的ID进行有放回随机抽样(Bootstrap)

基于ID的有放回抽样,确保总观测数恰好为指定值

给定如下数据:

Var1IDvar
1231
4562
7892
9873

希望基于IDvar进行有放回抽样,最终得到恰好4个观测。直接抽样IDvar会拆分同一ID的行(比如只抽中ID2的某一行);而抽样唯一ID时,又可能出现总观测数超出指定值的情况(比如抽中ID3、1、1、2,总观测数为1+1+1+2=5)。

高效实现方法

我们可以通过迭代抽样的方式,每次只选择行数不超过剩余所需样本量的ID,确保总观测数最终恰好等于目标值。以下是R语言的具体实现:

步骤1:定义数据

df <- data.frame(
  Var1 = c(123, 456, 789, 987),
  IDvar = c(1, 2, 2, 3)
)

步骤2:实现抽样函数

sample_by_id <- function(df, id_col, n) {
  # 统计每个ID对应的行数
  id_counts <- table(df[[id_col]])
  remaining <- n
  selected_ids <- c()
  
  while (remaining > 0) {
    # 筛选出当前可选择的ID(行数不超过剩余样本量)
    eligible_ids <- names(id_counts)[id_counts <= remaining]
    if (length(eligible_ids) == 0) {
      stop("无法达到指定样本量:所有ID的行数均大于剩余需要的样本量")
    }
    # 有放回随机抽取一个ID
    chosen_id <- sample(eligible_ids, 1, replace = TRUE)
    selected_ids <- c(selected_ids, chosen_id)
    # 更新剩余所需样本量
    remaining <- remaining - id_counts[chosen_id]
  }
  
  # 根据选中的ID重复提取对应行
  result <- do.call(rbind, lapply(selected_ids, function(id) {
    df[df[[id_col]] == id, ]
  }))
  
  return(result)
}

步骤3:调用函数

# 抽取4个观测
set.seed(123) # 设置随机种子保证结果可复现
sampled_df <- sample_by_id(df, "IDvar", 4)
print(sampled_df)

示例输出(因随机抽样可能不同):

Var1 IDvar
1  123     1
2  456     2
3  789     2
4  123     1

关于逐个抽样检查思路的效率评价

你提出的“逐个抽样ID并检查剩余样本量”的思路是完全可行的,且实际效率并不低:

  • 每次循环仅需执行简单的筛选和抽样操作,循环次数最多等于目标样本量(最坏情况每次选择行数为1的ID),但大多数场景下循环次数远小于目标值;
  • 相比拒绝抽样(反复生成整批ID直到总行数符合要求),这种方法更稳定,不会出现连续多次抽样失败的情况;
  • 代码逻辑清晰,易于理解和维护,对于绝大多数实际数据规模来说,性能开销可以忽略。

内容的提问来源于stack exchange,提问作者Aku-Ville Lehtimäki

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 17:40:34