如何使用加权采样连接数据?

Posted

技术标签:

【中文标题】如何使用加权采样连接数据?【英文标题】:How to join data with a weighted sampling? 【发布时间】:2021-10-04 13:13:58 【问题描述】:

我希望在两个数据集之间进行加权连接:

library(tidyverse)
set.seed(1)

test.sample <- data.frame(zip=sample(1:3,50,replace = TRUE))

index.dat <- data.frame(zip=c(1,1,2,3,3,3),
                  fips=c("A1", "A2", "B", "C1", "C2","C3"),
                  prob=c(.75,.25,1,.7,.2,.1))

我的预期输出将是索引数据集中的加权样本:

results1 <- c(rep("A1",14),rep("A2",4),rep("B",19,),rep("C1",9),rep("C2",3),"C3")

最终尝试从人口的概率分布中加入与多个 fips 代码匹配的邮政编码。

这条评论很好地描述了我正在努力克服的问题:https://***.com/a/13316857/4828653

这是我想出的一个潜在解决方案,但鉴于我有数十亿条记录,我需要性能更高的解决方案。

test_function <- function(x) 
index.dat %>% 
filter(zip == x) %>% 
sample_n(size=1,weight=prob) %>% 
select(fips)


results2 <- lapply(test.sample$zip, function(x) test_function(x)) %>% 
unlist() %>% 
data.frame(fips = .)

> table(results1)
results1
A1 A2  B C1 C2 C3 
14  4 19  9  3  1 
> table(results2)
results2
A1 A2  B C1 C2 C3 
15  3 19  8  2  3 

【问题讨论】:

在使用sample()等函数时请使用set.seed(),以保证重现性 我在 Cs 上的错误。根据人口分布为fips分配概率。这些只是我为一个简单示例设置的任意值。 我不明白的是A1A2 组合的概率为 1,得到 14 + 5 = 19 行。 B 的概率为 1,得到 20 行,而 C 的组合概率为 1,它们只有 11 行。如何以相同的概率获得不同的行数?那里的逻辑是什么? 我已将结果数调整为种子 = 1。 【参考方案1】:

您可以根据zip 拆分index.dat,以提供每个邮政编码的数据框列表。如果您使用test.sample$zip 对该列表进行子集化,您将获得一个包含 50 个数据框以及相应邮政编码的列表。然后,您可以使用每个数据帧的 prob 列中的权重对 fip 进行采样。

在你的情况下,看起来像这样:

sample_space <- split(index.dat, index.dat$zip)[test.sample$zip]

test.sample$fips <- sapply(sample_space, 
                           function(x) sample(x$fips, 1, prob = x$prob))

现在test.sample$fips 将从适当的邮政编码中随机选择一个 fip,并根据相对权重进行抽样。如果我们做一个test.sampl$fips的表格,我们可以看到比例差不多:

table(test.sample$fips)

#> A1 A2  B C1 C2 
#> 13  5 19 10  3 

zip 1 的 18 名成员以(几乎)75:25 的比例分配到 A1 和 A2。正如预期的那样,zip 2 的所有成员都被赋予了 B,并且 zip 3 的 13 个成员已被适当分配(尽管由于概率低,偶然没有选择 C3)

如果test.sample 有 5000 行,由于大数定律,我们会看到比例更接近预期的权重:

#>   A1   A2    B   C1   C2   C3 
#> 1257  419 1687 1153  325  159 

【讨论】:

这将如何扩展?我的样本空间有数十亿,并且有超过 40k 的邮政编码。我在上面使用了一个 lapply,我认为它可能更容易并行化,但仍然不是很好。 @SCDCE 它是线性扩展的——它应该是 O(n) 复杂度。在这里任何解决方案都会遇到的问题是内存使用情况。只要您能够执行并存储等效于 split(index.dat, index.dat$zip) 的内容,以提供包含 40,000 个邮政编码的参考列表以及相关的带有权重的 fip,那么您就可以一次进行一个块的采样。 我试试看,谢谢你的时间!

以上是关于如何使用加权采样连接数据?的主要内容,如果未能解决你的问题,请参考以下文章

如何在jmeter tcp采样器中发送多个十六进制数据有效负载?

如何在 jmeter 中关闭 JDBC 连接

推荐算法之加权采样

如何使用 sklearn 训练算法对数据点进行加权

解决正负样本数据不平衡

来自 2d numpy 数组的加权随机采样