不同大小组的高效递归随机抽样

tmf*_*mnk 6 recursion performance r

这个问题是我之前关于递归随机采样高效递归随机采样问题的后续问题。当组大小相同或每组需要固定数量的样本时,该线程中的解决方案可以正常工作。然而,让我们想象一个数据集如下:

   ID1 ID2
1    A   1
2    A   6
3    B   1
4    B   2
5    B   3
6    C   4
7    C   5
8    C   6
9    D   6
10   D   7
11   D   8
12   D   9
Run Code Online (Sandbox Code Playgroud)

我们想要为每个 ID1 随机采样最多 n 个ID2,并递归地执行此操作。这里的递归意味着我们从第一个 ID1 移动到最后一个 ID1,如果 ID2 已经被采样为 ID1,那么它不应该用于后续的 ID1。假设n = 2,那么预期结果如下;

ID1 ID2
1    A   1
2    A   6
4    B   2
5    B   3
6    C   4
7    C   5
11   D   8
12   D   9
Run Code Online (Sandbox Code Playgroud)
  • 对于ID1 =“A”,正好有两个潜在的ID2,因此两者都被选择。
  • 对于ID1 =“B”,还有两个潜在的ID2可供选择,因此两者都被选择。
  • 对于ID1 =“C”,还有两个潜在的ID2可供选择,因此两者都被选择。
  • 对于 ID =“D”,还剩下三个潜在的 ID2 可供采样,因此从其中随机选择两个。

除了示例所示的情况之外,还会发生什么情况;

  • 每个 ID1始终有一个非零数量的可用 ID2,但是,所有这些 ID2 可能都已被使用。在这种情况下,ID1 应该被简单地省略。
  • 有可能 ID1 中没有一个具有 ID2 中指定的 n。在这种情况下,应检索最接近指定 n 的 n。
  • ID 不一定是seq(ID1).
  • ID2 也可以是类似于 ID1 的字符向量。

样本 df;

df <- structure(list(ID1 = c("A", "A", "B", "B", "B", "C", "C", "C", 
"D", "D", "D", "D"), ID2 = c(1, 6, 1, 2, 3, 4, 5, 6, 6, 7, 8, 
9)), class = "data.frame", row.names = c(NA, -12L))
Run Code Online (Sandbox Code Playgroud)

caz*_*man 1

以下功能似乎可以满足您的需求。基本上,它循环遍历每组ID1并选择相应ID2尚未采样的行。ID1然后它选择不同的行(在某些组具有重复值的情况下) 。样本大小将是或该组的行数中ID2的最小值。n

\n
sample <- function(df, n) {\n  `%notin%` <- Negate(`%in%`)\n  groups <- unique(df$ID1)\n  out <- data.frame(ID1 = character(), ID2 = character())\n  \n  for (group in groups) {\n    options <- df %>%\n      filter(ID1 == group,\n             ID2 %notin% out$ID2)\n    \n    chosen <- sample_n(options,\n                       size = min(n, nrow(options))) %>%\n      distinct()\n    \n    out <- rbind(out, chosen)\n  }\n  \n  out\n}\n\nset.seed(123)\nsample(df, 2)\n\n  ID1 ID2\n1   A   1\n2   A   6\n3   B   2\n4   B   3\n5   C   4\n6   C   5\n7   D   8\n8   D   9\n
Run Code Online (Sandbox Code Playgroud)\n

ID1一组hasID2已用完的情况:\n输入:

\n
# A tibble: 10 \xc3\x97 2\n   ID1     ID2\n   <chr> <dbl>\n 1 A         1\n 2 A         3\n 3 B         1\n 4 B         3\n 5 C         5\n 6 C         6\n 7 C         7\n 8 C         7\n 9 D        10\n10 D        20\n
Run Code Online (Sandbox Code Playgroud)\n

输出:

\n
sample(df2, 2)\n# A tibble: 6 \xc3\x97 2\n  ID1     ID2\n  <chr> <dbl>\n1 A         3\n2 A         1\n3 C         6\n4 C         7\n5 D        20\n6 D        10\n
Run Code Online (Sandbox Code Playgroud)\n