【问题标题】:How can I generate a random subsample of a population with specific requirements?如何生成具有特定要求的人口的随机子样本?
【发布时间】:2021-04-29 05:19:07
【问题描述】:

假设我有一个混合年龄和性别(可能还有其他属性)的人群,我想生成一个具有某些属性的随机子样本(可以替换),例如:

  • 样本大小 N
  • 50%的样本应该是年龄
  • 20% 的样本应为男性

我可以先随机选择 N/2 个年龄 =30 的人,但这可能没有正确的性别组合。我可以进行子选择并确保在年龄

如何生成此样本?如果我让它稍微复杂一些并指定范围怎么办:

  • 样本大小 N
  • 30 岁以下的 50-80%(该范围内的均匀概率)
  • 20-30% 男性(该范围内的概率一致)

我想有可能迭代生成这样的样本,交替修剪它以匹配每个要求直到收敛,但我不确定如何正确地做到这一点。最愚蠢的方法当然是只生成随机样本,如果它们不符合这些要求,则拒绝它们。

【问题讨论】:

标签: python r sampling


【解决方案1】:

编辑:

这是一个样本,其中 70% 为 30 岁以下,20% 为男性:

N <- 100000
orig_u30 <- 0.7
orig_male <- 0.2
set.seed(42)
my_sample <- data.frame(age = sample(c("under 30", "30+"), N, replace = T, 
                                     prob = c(orig_u30, 1 - orig_u30)),
                        gender = sample(c("M", "F"), N, replace = T, 
                                        prob = c(male, 1-male)))
addmargins(prop.table(table(my_sample$age, my_sample$gender)))
                 F       M     Sum
  30+      0.24292 0.05935 0.30227
  under 30 0.55675 0.14098 0.69773
  Sum      0.79967 0.20033 1.00000

假设我们想要一个子样本,这些子样本的权重为 30 岁以下 40% 和 40% 男性。我们可以通过根据我们想要的与我们拥有的的相对比例对每一行应用权重来实现这一点。

old_u30 = mean(my_sample$age == "under 30")
new_u30 = 0.4
weight_u30 = (new_u30 / old_u30) / ((1-new_u30) / (1-old_u30))

old_male = mean(my_sample$gender == "M")
new_male = 0.4
weight_male = (new_male / old_male) / ((1-new_male) / (1-old_male))

my_sample$weight = ifelse(my_sample$age == "under 30", weight_u30, 1) *
  ifelse(my_sample$gender == "M", weight_male, 1)

现在我们为每一行设置一个权重,使其趋向于期望的份额:

library(dplyr)
my_subsample <- sample_n(my_sample, 10000, replace = TRUE, weight = my_sample$weight)

addmargins(prop.table(table(my_subsample$age, my_subsample$gender)))

现在是 40% 的男性和 40% 的 30 岁以下:

                F      M    Sum
  30+      0.3683 0.2348 0.6031
  under 30 0.2375 0.1594 0.3969
  Sum      0.6058 0.3942 1.0000

原始答案:生成加权样本但未加权子样本

N <- 1000
median_age <- 30
male <- 0.2

my_sample <- data.frame(age = rpois(N, median_age),
           gender = sample(c("M", "F"), N, replace = T, prob = c(male, 1-male)))

median(my_sample$age) # will be 30 most runs
table(my_sample$gender) # will be around 200 / 1000

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-02
    • 1970-01-01
    • 2018-10-26
    • 2012-11-21
    • 1970-01-01
    • 2015-07-15
    • 2015-10-28
    • 1970-01-01
    相关资源
    最近更新 更多