【问题标题】:Stratified sampling with constraints带约束的分层抽样
【发布时间】:2020-09-27 16:41:35
【问题描述】:

我是 R 的新手,所以请耐心等待。

所以我试图以这样一种方式执行分层抽样,它将使用 2 列分层,但两列都满足特定值。

这是我的代码:

library(splitstackshape)
set.seed(1)
dat1 <- data.frame(ID = 1:100,
                   A = sample(c("AA", "BB", "CC", "DD", "EE"), 100, replace = TRUE),
                   B = sample(c(30,40,50),100,replace = TRUE), C = sample(c(1:10),100,replace = TRUE),
                   D = sample(c("CA", "NY", "TX"), 100, replace = TRUE),
                   E = sample(c("M", "F"), 100, replace = TRUE))

stratified(dat1, c("B", "C"), 0.1, select = list(B = 30, C = c(8:10)))

据我了解,此函数首先生成大小为 10% 的层,然后从中选择满足条件 B=30 和 c 在 8 到 10 之间的那些记录。

因此,阶层的规模从最初的 10% 减少。

我的问题是,有没有什么方法可以生成一个分层,该分层由其中 B 列的值为 30 而列 C 的值在 8 到 10 之间的记录组成 nrow()结果样本是原始数据帧的 10%?

我正在使用来自“splitstackshape”的stratified()。如果stratified() 无法处理,是否还有其他软件包可以执行此类操作?

【问题讨论】:

  • 在使用sample等功能时请使用set.seed,以保证重现性。

标签: r splitstackshape


【解决方案1】:

更新

从原始答案中的示例数据继续,我将使用两步过程:

  1. 创建一个包含您感兴趣的关卡的子集。

    sub1 <- as.data.table(dat1)[B == 30 & C %in% 8:10][order(C)]
    
  2. 找出您需要抽样的百分比。在这里,我将最终行数设置为 500,因为在获取子集时样本数据没有 1000 行。要获得所需的百分比,它就像所需的行数除以子集中的总行数一样简单......

    rows_wanted <- 500
    set.seed(2)
    out <- stratified(sub1, "C", rows_wanted/nrow(sub1))
    
    ## Check how many rows we have per group
    out[, .N, .(B, C)]
    #     B  C   N
    # 1: 30  8 157
    # 2: 30  9 169
    # 3: 30 10 174
    

原答案

stratified 函数首先过滤数据,然后进行采样。考虑以下几点:

library(splitstackshape)
set.seed(1)
n <- 10000
dat1 <- data.frame(ID = sequence(n),
                   A = sample(c("AA", "BB", "CC", "DD", "EE"), n, replace = TRUE),
                   B = sample(c(30,40,50),n,replace = TRUE), 
                   C = sample(c(1:10),n,replace = TRUE),
                   D = sample(c("CA", "NY", "TX"), n, replace = TRUE),
                   E = sample(c("M", "F"), n, replace = TRUE))

样品,如您所见。

mySample <- stratified(dat1, c("B", "C"), 0.1, select = list(B = 30, C = 8:10))
nrow(mySample)
# [1] 98

将其与输出中预期的行数进行比较:

as.data.table(dat1)[, .N, .(B, C)][B == 30 & C %in% 8:10, list(N = round(N * .1)), .(B, C)][order(C)]
#     B  C  N
# 1: 30  8 31
# 2: 30  9 33
# 3: 30 10 34

并将上面的内容与您从 stratified 函数中获得的内容进行比较。

mySample[, .N, .(B, C)]
#     B  C  N
# 1: 30  8 31
# 2: 30  9 33
# 3: 30 10 34

【讨论】:

  • 对不起,如果我错了,请纠正我,但在您的代码中,原始数据框的大小为 10000。当您以 10% 的大小以及列约束对其进行采样时,生成的样本nrow() 为 98(这是我最初的问题),不是初始数据帧的 10%(在这种情况下为 1000)。请允许我重新表述我的问题,我正在尝试找到一种方法来使用列约束进行分层抽样,样本的大小不会从给定的 10% 变化。我希望我能让自己被理解。
  • @Rowen,请查看我的更新,如果这与您尝试做的事情相符,请告诉我。
【解决方案2】:

根据您的数据,这似乎是不可能的,至少如果您在没有替换的情况下进行抽样。

idx <- which((dat1$B == 30) & (dat1$C %in% 8:10))
idx <- sample(idx, 0.1*nrow(dat1))

sample.int(length(x), size, replace, prob) 中的错误:
'replace = FALSE' 时不能抽取大于总体的样本

问题在于验证这两个条件的行数不到您数据的 10%。向量idx 的长度只有 5。

idx
#[1] 15 18 43 60 93

dat1[idx, ]
#   ID  A  B  C  D E
#15 15 DD 30  9 CA F
#18 18 EE 30 10 NY M
#43 43 DD 30 10 NY F
#60 60 CC 30 10 NY M
#93 93 DD 30 10 TX M

【讨论】:

  • 实际上,我只是在样本数据上对此进行了测试。我的实际数据包含大约 10 M 条记录。如果我错了,请纠正我,但是 sample() 只是进行随机抽样,对吗?其实我想做分层抽样。
  • @Rowen 你说得对,sample 只是随机抽样。对于分层抽样,请查看包sampling,函数strata
  • 我做到了,但我没有注意到任何提供基于列的条件的方法。如果您确实遇到类似的事情,请务必让我知道。谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-13
  • 1970-01-01
  • 2017-10-22
  • 2017-10-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多