r语言 - 分层随机抽样,没有重复的 ID



我有一个数据集,其中每个id有多个样本,可以分层为group变量。我想做随机抽样,按group分层,但不要重复id(即每个id在输出中只出现一次)。

我试图修改一些现有的解决方案,但是,似乎都对数据进行了采样,并包括来自跨组的单个id的多个样本:

  • 随机抽样 - 矩阵
  • 从数据框分层随机抽样
  • R 中的分层随机抽样
  • 从数据框分层随机抽样

我已经尝试了以下内容,认为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在第1 和 2group重复。我想要的理想输出应该是这样的,其中每个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() 

最新更新