首页 > 解决方案 > 没有重复 ID 的分层随机抽样

问题描述

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

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

我尝试了以下方法,认为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在group1 和 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。感谢您的任何帮助!

标签: rrandomsampling

解决方案


我有一个候选解决方案,使用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)
        )
        
        
        
}

如果初始值具有特定存在,则此算法与data您提供的算法一起工作,否则,唯一 ID 的可用性将耗尽。sampled_dataids

该算法首先使用 将数据拆分到各个组中split,然后打乱 的顺序以在函数list中引入随机性。distinct

初始抽样

我们首先sample从第一组中获取一个,然后作为其余组的基线。

它首先id从基线样本中存在的下一个索引中删除所有。然后采样并将其绑定到列表,并创建一个data.frame.

下一个样本

新的data.framenow 包含在 中不同的前两个组,并从其中存在的剩余索引中id删除。iddata.frame

最终产品如下;

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,因为我很难找到一个合适的。


推荐阅读