【问题标题】:Generate random sample using weights by group按组使用权重生成随机样本
【发布时间】:2018-10-24 19:17:39
【问题描述】:

我正在尝试使用组随机抽样data.table。每个组的样本大小将通过将频率乘以Sample_Size 来计算,这是输出data.table 中的预期行数。

我在 SO 上研究了这个主题。似乎类似的线程(Need to randomly sample a data set with multiple groups each with multiple factorstake randomly sample based on groups)假设权重分布均匀,这对我不起作用。

这是测试数据:

InputDT <- data.table::data.table ("Country"=c(rep("A",20),rep("B",10),rep("C",5),rep("D",2)), "ID"=c(1:20,101:110,201:205,301:302))

目标是按国家/地区对 ID 进行抽样。

这是我们想要的频率:

CountryFreq <- 
 data.table::data.table("Country"=unique(InputDT$Country), "Freq"=c(4/10,2/10,2/10,2/10))

这是输出data.table中的行数:

 Sample_Size <- 10

作为一项规则,我们假设Sample_Size &lt; nrows(InputDT)

这是手动创建的示例输出:

OutputDT <- structure(list(Country = c("A", "A", "A", "A", "B", "B", "C", 
"C", "D", "D"), ID = c(1, 5, 7, 3, 102, 109, 203, 204, 301, 302
)), .Names = c("Country", "ID"), row.names = c(NA, 10L), class = "data.frame")

这是一个检查频率是否符合需要的测试:

Hmisc::describe(OutputDT$Country)

OutputDT$Country 
       n  missing distinct 
      10        0        4 

Value        A   B   C   D
Frequency    4   2   2   2
Proportion 0.4 0.2 0.2 0.2

有人可以帮帮我吗?我花了将近一天的时间尝试学习 R 中的采样,然后根据我的需要对其进行自定义。如有任何帮助,我将不胜感激。

【问题讨论】:

  • 我们是否需要使用CountryFreq数据
  • @akrun - 是的,akrun。绝对地。这有我们想要的每个国家/地区的频率。

标签: r random data.table


【解决方案1】:

您可以先以国家频率加入InputDT,然后再对每个国家/地区进行如下抽样:

InputDT[CountryFreq,
    .SD[sample(.N, min(.N, Freq*Sample_Size))], 
    by=.EACHI,
    on=.(Country)]

注意事项:

InputDT[i=CountryFreq, on=.(Country)] 以 Country 作为键将 CountryFreq 与 InputDT 连接起来。

by=.EACHIi=CountryFreq 中的每一行执行此j=.SD[sample(.N, min(.N, Freq*Sample_Size))]。注意 by=.EACHI 目前仅适用于 equi-join。

.SDInputDT 的数据子集,即i 的每一行中每个Country 的每个InputDT 的数据子集,因为by=.EACHI.SD 只是真正在InputDT 范围内,只能在j 中使用。见?data.table。要了解更多信息,请查看词法作用域。 Hadley Wickham 的 Advanced R 是一个很好的参考。

sample(.N, min(.N, Freq*Sample_Size)).SD 的行数中采样Freq*Sample_Size 索引,而min 确保您采样的样本不会超过该国家/地区的可用样本。

最后,.SD[sample(.N, min(.N, Freq*Sample_Size))] 子集采样了 .SD 的行。


编辑:从 R 控制台显示示例运行。

> InputDT[CountryFreq,
+     .SD[sample(.N, min(.N, Freq*Sample_Size))], 
+     by=.EACHI,
+     on=.(Country)]
    Country  ID
 1:       A  19
 2:       A   7
 3:       A   5
 4:       A   3
 5:       B 109
 6:       B 110
 7:       C 203
 8:       C 205
 9:       D 302
10:       D 301
> InputDT[CountryFreq,
+     .SD[sample(.N, min(.N, Freq*Sample_Size))], 
+     by=.EACHI,
+     on=.(Country)]
    Country  ID
 1:       A  12
 2:       A  19
 3:       A  17
 4:       A  10
 5:       B 110
 6:       B 105
 7:       C 202
 8:       C 203
 9:       D 302
10:       D 301
> InputDT[CountryFreq,
+     .SD[sample(.N, min(.N, Freq*Sample_Size))], 
+     by=.EACHI,
+     on=.(Country)]
    Country  ID
 1:       A   9
 2:       A   7
 3:       A  19
 4:       A   6
 5:       B 106
 6:       B 108
 7:       C 205
 8:       C 201
 9:       D 302
10:       D 301

【讨论】:

  • 谢谢,但我无法获得所需的输出。来自 A 国的 ID 是随机选择的,而不是 B、C 和 D 国。不知道为什么。能否请你帮忙?学习不同的方法来做同样的事情总是有帮助的。提前致谢。
  • 当我重新运行代码时,我得到了不同的 A、B 和 C 值。 D 只有 2 个样本,因此从 2 个样本中抽取 2 个样本将始终返回相同的结果
  • 感谢 chinsoon。我从 A 获取 B、C 和 D 的值。B 的值应该在 1xx 范围内,C 应该有 2xx 范围,D 应该有 3xx 范围,但我得到的所有值都在 xx 范围内,属于 A。如果你在下面运行 akrun 的代码,你会有所不同。 akrun 的代码运行完美。
  • 添加了一些示例运行。我认为是因为今天早些时候代码丢失了.SD
  • 非常感谢。精彩的。如果你不介意的话,你能解释一下你的代码吗?这样,读者就可以了解发生了什么。提前致谢。
【解决方案2】:

我们可以的

InputDT[, rbindlist(Map(function(x, y) x[sample(seq_len(nrow(x)), y)], 
        split(.SD, Country), freq))]

数据

freq <- c(4, 2, 2, 2)

【讨论】:

  • 感谢您的帮助。我相信这段代码只有在InputDT 按照freq 排序时才有效,这意味着freqCountry 之间必须存在1-1 映射拆分。对吗?
  • @watchtower 我假设频率是相同的顺序
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-12-22
  • 2015-09-10
  • 2010-10-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多