r - 没有重复 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在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)
)
}
如果初始值具有特定存在,则此算法与data
您提供的算法一起工作,否则,唯一 ID 的可用性将耗尽。sampled_data
ids
该算法首先使用 将数据拆分到各个组中split
,然后打乱 的顺序以在函数list
中引入随机性。distinct
初始抽样
我们首先sample
从第一组中获取一个,然后作为其余组的基线。
它首先id
从基线样本中存在的下一个索引中删除所有。然后采样并将其绑定到列表,并创建一个data.frame
.
下一个样本
新的data.frame
now 包含在 中不同的前两个组,并从其中存在的剩余索引中id
删除。id
data.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
,因为我很难找到一个合适的。
推荐阅读
- ios - 如何在访问用户位置时添加自定义消息?
- python - 使用递归函数对整数进行洗牌
- azure-ad-b2c - Azure B2C - 如何添加额外的身份验证字段?
- python-3.x - 如何在熊猫数据框上制作矩形矩阵正方形
- sql - 如何 PIVOT SQL 表
- android - android clip儿童不工作cornerRadius形状
- mysql - 从大型 IEnumerable 中获取计数
- hadoop - 如何从在 Ubuntu 16.04 上运行的 hadoop 3.0.3 卸载 sqoop-1.99.7
- javascript - 列包装jsPDF自动表不起作用?
- flutter - 在创建带有浮动应用栏的应用时使用 StreamBuilder