這個問題是我之前關于 recursive random sampling Efficient recursive random sampling的問題的后續問題。當組大小相同或每組需要固定數量的樣本時,該執行緒中的解決方案可以正常作業。但是,讓我們想象一個資料集如下;
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
我們希望為每個 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
- 對于 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))
uj5u.com熱心網友回復:
以下功能似乎可以滿足您的需求。基本上,它遍歷每一組ID1并選擇對應ID2的未被采樣的行。然后它選擇不同的行(在某些組ID1具有重復ID2值的情況下。樣本量將是n或該組的行數中的最小值。
sample <- function(df, n) {
`%notin%` <- Negate(`%in%`)
groups <- unique(df$ID1)
out <- data.frame(ID1 = character(), ID2 = character())
for (group in groups) {
options <- df %>%
filter(ID1 == group,
ID2 %notin% out$ID2)
chosen <- sample_n(options,
size = min(n, nrow(options))) %>%
distinct()
out <- rbind(out, chosen)
}
out
}
set.seed(123)
sample(df, 2)
ID1 ID2
1 A 1
2 A 6
3 B 2
4 B 3
5 C 4
6 C 5
7 D 8
8 D 9
一組已經用完的ID1has的情況:輸入:ID2
# A tibble: 10 × 2
ID1 ID2
<chr> <dbl>
1 A 1
2 A 3
3 B 1
4 B 3
5 C 5
6 C 6
7 C 7
8 C 7
9 D 10
10 D 20
輸出:
sample(df2, 2)
# A tibble: 6 × 2
ID1 ID2
<chr> <dbl>
1 A 3
2 A 1
3 C 6
4 C 7
5 D 20
6 D 10
uj5u.com熱心網友回復:
我不知道我是否過度簡化了問題。請查看以下內容,看看它是否適用于您的情況:
library(tidyverse)
df %>%
group_split(ID1)%>%
reduce(~ bind_rows(.x, .y) %>%
filter(!duplicated(ID2))%>%
group_by(ID1)%>%
slice_sample(n=2) %>%
ungroup,
.init = slice_sample(.[[1]], n=2))
# A tibble: 8 x 2
ID1 ID2
<chr> <dbl>
1 A 1
2 A 6
3 B 2
4 B 3
5 C 4
6 C 5
7 D 9
8 D 8
免責宣告:未矢量化,因此效率低下
uj5u.com熱心網友回復:
這是使用動態規劃 (DP) 的基本 R 選項
d <- table(df)
nms <- dimnames(d)
res <- list()
for (i in nms$ID1) {
idx <- which(d[i, ] > 0)
if (length(idx) >= 2) {
j <- sample(idx, 2)
res[[i]] <- nms$ID2[j]
d[, j] <- 0
}
}
dfout <- type.convert(
setNames(rev(stack(res)), names(df)),
as.is = TRUE
)
這使
ID1 ID2
1 A 6
2 A 1
3 B 2
4 B 3
5 C 4
6 C 5
7 D 7
8 D 8
對于ID2已經使用的情況,例如,
> (df <- structure(list(ID1 = c(
"A", "A", "B", "B", "B", "C", "C", "C",
"D", "D", "D", "D"
), ID2 = c(
1, 3, 1, 2, 3, 3, 4, 5, 4, 5, 6, .... [TRUNCATED]
ID1 ID2
1 A 1
2 A 3
3 B 1
4 B 2
5 B 3
6 C 3
7 C 4
8 C 5
9 D 4
10 D 5
11 D 6
12 D 1
我們將獲得
ID1 ID2
1 A 1
2 A 3
3 C 5
4 C 4
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/422644.html
標籤:
上一篇:如何從AndroidStudioBumblebee隱藏縮放控制器?
下一篇:Kotlin集合操作的有效性
