如何通过加权抽样加入数据?
How to join data with a weighted sampling?
我希望在两个数据集之间进行加权连接:
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 代码匹配的邮政编码。
这条评论很好地描述了我要克服的问题:
这是我想出的一个潜在解决方案,但考虑到我有数十亿条记录,我需要性能更高的东西。
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
您可以根据 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,我们可以看到比例大约是正确的:
table(test.sample$fips)
#> A1 A2 B C1 C2
#> 13 5 19 10 3
zip 1 的 18 个成员已分配给 A1 和 A2,(几乎)75:25 拆分。正如预期的那样,zip 2 的所有成员都得到了 B,并且 zip 3 的 13 个成员已被适当分配(尽管由于概率低而偶然没有选择 C3)
如果 test.sample
有 5000 行,由于大数定律,我们会发现比例更接近预期的权重:
#> A1 A2 B C1 C2 C3
#> 1257 419 1687 1153 325 159
我希望在两个数据集之间进行加权连接:
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 代码匹配的邮政编码。
这条评论很好地描述了我要克服的问题:
这是我想出的一个潜在解决方案,但考虑到我有数十亿条记录,我需要性能更高的东西。
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
您可以根据 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,我们可以看到比例大约是正确的:
table(test.sample$fips)
#> A1 A2 B C1 C2
#> 13 5 19 10 3
zip 1 的 18 个成员已分配给 A1 和 A2,(几乎)75:25 拆分。正如预期的那样,zip 2 的所有成员都得到了 B,并且 zip 3 的 13 个成员已被适当分配(尽管由于概率低而偶然没有选择 C3)
如果 test.sample
有 5000 行,由于大数定律,我们会发现比例更接近预期的权重:
#> A1 A2 B C1 C2 C3
#> 1257 419 1687 1153 325 159