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)
除了示例所示的情况之外,还会发生什么情况;
seq(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)
以下功能似乎可以满足您的需求。基本上,它循环遍历每组ID1并选择相应ID2尚未采样的行。ID1然后它选择不同的行(在某些组具有重复值的情况下) 。样本大小将是或该组的行数中ID2的最小值。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\nRun Code Online (Sandbox Code Playgroud)\nID1一组hasID2已用完的情况:\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\nRun Code Online (Sandbox Code Playgroud)\n输出:
\nsample(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\nRun Code Online (Sandbox Code Playgroud)\n