r - 有限制的分层抽样: fixed total size evenly partitioned among groups

标签 r partitioning

我有一些分组数据,每项一行。 我想按组进行分层抽样,有两个限制:(1)一定的总样本量; (2) 样本应尽可能均匀地在组之间划分(即组样本大小的最小 sd)。

理想情况下,我们从每个组中选择相同(固定)数量的项目,当组大小>=所有组所需的大小时,这没有问题。但是,有时组大小小于 size。但项目总数始终高于样本总数。例如,总样本量为 12,有四个不同的组,我们理想情况下希望从每个组中挑选 3 个项目

size_tot <- 12
n_grp <- 4
size <- size_tot / n_grp

一些数据:

d2 <- data.table(id = 1:16,
                 grp = rep(c("a", "b", "c", "d"), c(9, 4, 2, 1)))
d2
#     id grp
#  1:  1   a
#  2:  2   a
#  3:  3   a
#  4:  4   a
#  5:  5   a
#  6:  6   a
#  7:  7   a
#  8:  8   a
#  9:  9   a
# 10: 10   b
# 11: 11   b
# 12: 12   b
# 13: 13   b
# 14: 14   c
# 15: 15   c
# 16: 16   d

我最初的逻辑是“如果项目数量等于或大于 size,则从组中抽取 size 个项目,否则只需从组中选取所有项目组”。另请参阅here , herehere .

set.seed(1)
d2[ , if(.N >= size) .SD[sample(x = .N, size = size)] else .SD, by = "grp"]

#    grp id
# 1:   a  3
# 2:   a  9
# 3:   a  5
# 4:   b 13
# 5:   b 10
# 6:   b 11
# 7:   c 14
# 8:   c 15
# 9:   d 16

在拥有足够数量项目(a 和 b)的两组中,我们从每组中抽取了 3 个项目。在小组(c 和 d)中,我们只选择了所有的,即分别为 2 和 1。这导致总样本量为 9,即小于所需的总样本量 12。因此,我们需要从具有剩余项目的较大组中抽取额外项目,以达到所需的总样本量。在这种情况下,所需的采样将是来自“b”的 1 个附加项目和来自“a”的两个附加项目。

以下是我对 sd 最低的分区的看法。总样本量可以分为四组,如下所示:

library(partitions)
cmp <- compositions(n = size_tot, m = 4)

然后可以将分区按从低 sd(组间样本大小相等 - 需要)到高 sd 的顺序排列:

std <- apply(cmp, 2, sd)
cmp2 <- cmp[ , order(std)]

cmp2[ , 1:10]
#      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
# [1,]    3    4    3    3    4    3    4    2    3     2
# [2,]    3    3    4    3    3    4    2    4    2     3
# [3,]    3    3    3    4    2    2    3    3    4     4
# [4,]    3    2    2    2    3    3    3    3    3     3

以及组大小:

d1[ , .(n = .N), by = "grp"]
#    grp n
# 1:   a 9
# 2:   b 4
# 3:   c 2
# 4:   d 1

但是如何将此分区(总和为 12)与组样本大小(总和不一定为 12)相匹配?这里还有其他人闻到 XY 问题吗?因此,是否有我忽略的替代方法?

<小时/>

PS:我考虑过比例分配(比例抽样),但是 当组大小的分布充分倾斜时,此类采样显然不尊重绝对总样本量,并且不会在组之间均匀分配样本(例如 caret::createDataPartitionstrata::balancedstratification)

最佳答案

我想你的答案已经差不多了。您只需要对 cmp2 进行过滤即可获得满足采样大小小于或等于组大小的条件的第一个采样集:

#Create a set of indices of sampling sizes that fit the criteria
original_groups <- d2[, .N, by = grp][,N]
valid_indexes <- apply(cmp2, 2, function(x) all(x <= original_groups))

#Take the first of these valid indices (lowest variance)
sampling_sizes <- cmp2[,which(valid_indexes)[1]]

#Create a sampling size variable on the datatable
d2[, sampling_size := rep(sampling_sizes, original_groups)]

#Sample as before
d2[ , .SD[sample(x = .N, size = sampling_size)], by = "grp"]

关于r - 有限制的分层抽样: fixed total size evenly partitioned among groups,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35800181/

相关文章:

r - 更新 R 中的 csv header ,无需重写整个文件

r - 将回归线添加到绘图 (plotmeans)

cassandra - 当复制因子 == 集群大小时,Cassandra 分区如何工作?

Azure 事件中心通过分区进行流分析

scala - 如何根据行数重新分区 Spark 数据帧?

r - glmnet 的标准化参数如何处理虚拟变量?

r - 包 tm : removeWords How do I avoid removing CERTIAN (negations specifically) "english" stopwords if specified?

r - 计算R中的移动多数

java - 在 Pivot 上对数组进行分区

sql-server - 如何在 SQL Server 中结合水平和垂直分区