1

假设我有一个包含 1,000,000 个观测值的数据集。变量是年龄、种族、性别。这个数据集代表了整个美国。

给定一定的年龄分布,我如何从这个数据集中抽取 1000 人的样本?例如,我想要这个包含 1000 人的数据集,分布如下:

0.3 * 年龄 0 - 30

0.3 * 年龄 31 - 50

0.2 * 年龄 51 - 69

0.2 * 年龄 70 - 100

有没有快速的方法来做到这一点?我已经创建了具有所需年龄分布的 1000 人的样本,但是我现在如何将其与我的原始数据集结合起来呢?

例如,这就是我创建缅因州人口分布的方式:

set.seed(123)
library(magrittr) 

    popMaine <- data.frame(min=c(0, 19, 26, 35, 55, 65), max=c(18, 25, 34, 54, 64, 113), prop=c(0.2, 0.07, 0.11, 0.29, 0.14, 0.21))

    Mainesample <- sample(nrow(popMaine), 1000, replace=TRUE, prob=popMaine$prop)

    Maine <- round(popMaine$min[Mainesample] + runif(1000) * (popMaine$max[Mainesample] - popMaine$min[Mainesample])) %>% data.frame()

    names(Texas) <- c("Age")

现在我不知道如何将它与拥有整个美国人口的其他数据集结合在一起......我会很感激任何帮助,我现在被困了很长一段时间......

4

1 回答 1

1

以下是四种不同的方法。两个使用函数分别来自splitstackshapeandsampling包,一个使用 base mapply,一个使用map2来自purrr包(tidyverse包集合的一部分)。

首先让我们设置一些假数据和采样参数:

# Fake data
set.seed(156)
df = data.frame(age=sample(0:100, 1e6, replace=TRUE))

# Add a grouping variable for age range
df = df$age.groups = cut(df$age, c(0,30,51,70,Inf), right=FALSE)

# Total number of people sampled
n = 1000

# Named vector of sample proportions by group
probs = setNames(c(0.3, 0.3, 0.2, 0.2), levels(df$age.groups))

使用上述采样参数,我们希望从每个年龄组中n按比例对总值进行采样。probs

选项1:mapply

mapply可以对一个函数应用多个参数。在这里,参数是 (1) 数据框df分为四个年龄组,以及 (2) probs*n,它给出了我们想要从每个年龄组中获得的行数:

df.sample = mapply(a=split(df, df$age.groups), b=probs*n, 
       function(a,b) {
         a[sample(1:nrow(a), b), ]
       }, SIMPLIFY=FALSE)

mapply返回一个包含四个数据帧的列表,每个数据帧一个。将此列表组合成一个数据框:

df.sample = do.call(rbind, df.sample)

检查抽样:

table(df.sample$age.groups)
[0,30)  [30,51)  [51,70) [70,Inf) 
   300      300      200      200

选项 2:包stratified中的函数splitstackshape

size参数需要一个命名向量,其中包含每个层的样本数。

library(splitstackshape)

df.sample2 = stratified(df, "age.groups", size=probs*n)

选项 3:包strata中的函数sampling

这个选项是迄今为止最慢的。

library(sampling)

# Data frame must be sorted by stratification column(s)
df = df[order(df$age.groups),]

sampled.rows = strata(df, 'age.groups', size=probs*n, method="srswor")

df.sample3 = df[sampled.rows$ID_unit, ] 

选项 4:tidyverse

map2就像mapply它将两个参数并行应用于一个函数,在这种情况下是dplyr包的sample_n函数。map2返回四个数据框的列表,每个层一个,我们将它们组合成一个数据框bind_rows

library(dplyr)
library(purrr)

df.sample4 = map2(split(df, df$age.groups), probs*n, sample_n) %>% bind_rows

计时

library(microbenchmark)
Unit: milliseconds
       expr        min         lq       mean     median         uq       max neval cld
     mapply   86.77215  110.82979  156.66855  123.95275  145.25115  486.2078    10  a 
     strata 5028.42933 5541.40442 5709.16796 5699.50711 5845.69921 6467.7250    10   b
 stratified   38.33495   41.76831   89.93954   45.43525   79.18461  408.2346    10  a 
  tidyverse   71.48638  135.49113  143.12011  142.86866  155.72665  192.4174    10  a
于 2016-11-01T02:16:28.937 回答