没有重复 ID 的分层随机抽样
Stratified random sampling with no repeated IDs
我有一个数据集,其中每个 id
都有多个样本,可以分层到 group
变量中。我想进行随机抽样,按 group
分层,但不重复 id
(即每个 id
只在输出中出现一次)。
我试图修改一些现有的解决方案,但是,所有解决方案似乎都对数据进行了采样,并包括来自单个 id
的多个样本:
- random sampling - matrix
- Stratified random sampling from data frame
- Stratified random sampling from data frame
我尝试了以下方法,认为 replace = FALSE
可能有助于确保每个 id
中只使用 1 个样本,但这仍然不能满足我的要求。
set.seed(1)
# Data
data <- data.frame(
id = c("A", "C", "B", "D", "E", "F", "A", "A", "B", "B", "B", "D", "D", "E", "E", "F"),
group = c("1", "1", "2", "2", "3", "3", "2", "1", "1", "2", "3", "2", "3", "2", "1", "3"),
length = c("54", "52", "43", "42", "60", "46", "59", "60", "51", "45", "47", "58", "48", "46", "56", "57"))
# Stratified random sampling by group
sample <- data %>%
distinct %>%
group_by(group) %>%
sample_n(2, replace = FALSE) %>%
left_join(data)
sample
输出:
id group length
A 1 60
C 1 52
D 2 42
A 2 59
B 3 47
E 3 60
然而,如上所示,id
= A在group
1和2中重复出现.我想要的理想输出应该看起来像这样,其中每个 id
只出现一次并且样本按 group
:
分层
id group length
A 1 54
C 1 52
B 2 43
D 2 42
E 3 60
F 3 46
有没有一种方法可以自定义现有的解决方案,以便在对每个 group
进行采样时,如果 id
已经用于另一个 group
,它将被排除在外并没有为另一个 group
采样?我知道我可以将 %>% distinct(id)
添加到我的代码中,但我相信这不再是随机的,因为 distinct()
只是选择 id
的第一行。感谢您的帮助!
我有一个候选解决方案,使用 for-loops
。当然,该解决方案有点尴尬,并且有一些与您提供的数据相关的警告。但是,该脚本按预期工作。
# Split by group; this provides
# a list with each group.
data_list <- data %>% split(
f = .$group
)
# shuffle the list to introduce
# randomness
shuffle <- sample(length(data_list))
data_list <- data_list[shuffle]
# Sample from the first indice
# which serves as a baseline for remaining
# samples
sampled_data <- data_list[[1]] %>%
distinct(id, .keep_all = TRUE) %>%
sample_n(2)
for (i in 2:length(data_list)) {
# Proceed to next group
new_data <- data_list[[i]]
indicator <- new_data$id %in% sampled_data$id
sampled_data <- bind_rows(
sampled_data,
new_data[!indicator,] %>% distinct(id, .keep_all = TRUE) %>% group_by(group) %>% sample_n(2)
)
}
如果初始 sampled_data
具有特定的 ids
,则此算法与您提供的 data
一起工作,否则唯一 ID 的可用性将耗尽。
该算法首先使用 split
将您的数据拆分到各个组中,然后打乱 list
的顺序以在 distinct
函数中引入随机性。
初始采样
我们首先从第一组中取 sample
,然后作为其余组的基线。
它首先从基线样本中存在的下一个索引中删除所有 id
。然后对其进行采样并将其绑定到列表,并创建一个 data.frame
.
下一个样本
新的 data.frame
现在由 id
中不同的前两组组成,并从 data.frame
中存在的剩余索引中删除 id
.
最终产品如下;
id group length
1 B 1 51
2 C 1 52
3 D 2 42
4 A 2 59
5 E 3 60
6 F 3 46
如果您提供的数据代表您的实际数据,显然该算法需要一些改进,因为根据 seed
,唯一值的可用性会根据您的初始 id
耗尽。
我没有提供 seed
因为我找不到合适的。
这是我最后使用的解决方案。
# Randomise rows
set.seed(x) # play around and set seed accordingly
data_rows <- sample(nrow(data))
data2 <- data[data_rows, ]
# Stratified random sampling
set.seed(x) # play around and set seed accordingly
randomised <- data2 %>%
distinct(id, .keep_all = TRUE) %>%
group_by(group) %>%
sample_n(2, replace = FALSE) %>%
ungroup()
我有一个数据集,其中每个 id
都有多个样本,可以分层到 group
变量中。我想进行随机抽样,按 group
分层,但不重复 id
(即每个 id
只在输出中出现一次)。
我试图修改一些现有的解决方案,但是,所有解决方案似乎都对数据进行了采样,并包括来自单个 id
的多个样本:
- random sampling - matrix
- Stratified random sampling from data frame
- Stratified random sampling from data frame
我尝试了以下方法,认为 replace = FALSE
可能有助于确保每个 id
中只使用 1 个样本,但这仍然不能满足我的要求。
set.seed(1)
# Data
data <- data.frame(
id = c("A", "C", "B", "D", "E", "F", "A", "A", "B", "B", "B", "D", "D", "E", "E", "F"),
group = c("1", "1", "2", "2", "3", "3", "2", "1", "1", "2", "3", "2", "3", "2", "1", "3"),
length = c("54", "52", "43", "42", "60", "46", "59", "60", "51", "45", "47", "58", "48", "46", "56", "57"))
# Stratified random sampling by group
sample <- data %>%
distinct %>%
group_by(group) %>%
sample_n(2, replace = FALSE) %>%
left_join(data)
sample
输出:
id group length
A 1 60
C 1 52
D 2 42
A 2 59
B 3 47
E 3 60
然而,如上所示,id
= A在group
1和2中重复出现.我想要的理想输出应该看起来像这样,其中每个 id
只出现一次并且样本按 group
:
id group length
A 1 54
C 1 52
B 2 43
D 2 42
E 3 60
F 3 46
有没有一种方法可以自定义现有的解决方案,以便在对每个 group
进行采样时,如果 id
已经用于另一个 group
,它将被排除在外并没有为另一个 group
采样?我知道我可以将 %>% distinct(id)
添加到我的代码中,但我相信这不再是随机的,因为 distinct()
只是选择 id
的第一行。感谢您的帮助!
我有一个候选解决方案,使用 for-loops
。当然,该解决方案有点尴尬,并且有一些与您提供的数据相关的警告。但是,该脚本按预期工作。
# Split by group; this provides
# a list with each group.
data_list <- data %>% split(
f = .$group
)
# shuffle the list to introduce
# randomness
shuffle <- sample(length(data_list))
data_list <- data_list[shuffle]
# Sample from the first indice
# which serves as a baseline for remaining
# samples
sampled_data <- data_list[[1]] %>%
distinct(id, .keep_all = TRUE) %>%
sample_n(2)
for (i in 2:length(data_list)) {
# Proceed to next group
new_data <- data_list[[i]]
indicator <- new_data$id %in% sampled_data$id
sampled_data <- bind_rows(
sampled_data,
new_data[!indicator,] %>% distinct(id, .keep_all = TRUE) %>% group_by(group) %>% sample_n(2)
)
}
如果初始 sampled_data
具有特定的 ids
,则此算法与您提供的 data
一起工作,否则唯一 ID 的可用性将耗尽。
该算法首先使用 split
将您的数据拆分到各个组中,然后打乱 list
的顺序以在 distinct
函数中引入随机性。
初始采样
我们首先从第一组中取 sample
,然后作为其余组的基线。
它首先从基线样本中存在的下一个索引中删除所有 id
。然后对其进行采样并将其绑定到列表,并创建一个 data.frame
.
下一个样本
新的 data.frame
现在由 id
中不同的前两组组成,并从 data.frame
中存在的剩余索引中删除 id
.
最终产品如下;
id group length
1 B 1 51
2 C 1 52
3 D 2 42
4 A 2 59
5 E 3 60
6 F 3 46
如果您提供的数据代表您的实际数据,显然该算法需要一些改进,因为根据 seed
,唯一值的可用性会根据您的初始 id
耗尽。
我没有提供 seed
因为我找不到合适的。
这是我最后使用的解决方案。
# Randomise rows
set.seed(x) # play around and set seed accordingly
data_rows <- sample(nrow(data))
data2 <- data[data_rows, ]
# Stratified random sampling
set.seed(x) # play around and set seed accordingly
randomised <- data2 %>%
distinct(id, .keep_all = TRUE) %>%
group_by(group) %>%
sample_n(2, replace = FALSE) %>%
ungroup()