我有一个数据集,想根据我手动设置的概率获取样本。
示例:(id = user,score(按desc排序),b1-b6(虚拟变量)), 1表示用户具有此功能,否则为0 < / p>
id score b1 b2 b3 b4 b5 b6
1 0.99 1 0 0 0 1 0
2 0.98 1 0 0 0 0 0
3 0.97 1 1 1 0 1 1
4 0.96 0 1 0 0 0 0
给出一个参数集( p1,p2,p3,p4,p5,p6 ),用于控制列中具有此功能的用户的比例(b1,b2,b3,b4,b5, b6)分别
让我们看看我设置p1 = 0.1,p2 = 0.2,p3 = 0.9,p4 = 0.32,p5 = 0.2,p6 = 0.21 并且期望从数据集中采样,其分布大致遵循p1-p6值。
大约10%的用户在b1中有1个,20%的用户在b2中有1个,依此类推)
问题是原始数据集的分布是否跨越b1到b6,以及如何分配 从中获取样本,其分布符合p1-p6值
任何想法都将不胜感激
更新 这是从大型数据集(1000k的1k样本)中绘制样本,该样本遵循分布(p1,p2等),而不是模拟虚假数据
方法1 :可以通过重复随机样本来解决。并使用最接近的一个(需要重新采样或迭代技巧)。
方法2 :使用线性优化算法(可能很复杂,因为2 ^ 6种可能性,需要求解大方程)
答案 0 :(得分:0)
亨利,正如评论中所建议的那样,有两种生成这类数据的通用方法。一种是计算“每个单元格将为0或1”的概率,另一种是“向量的随机抽样,以便选择n
%”。两者完全不同(至少在不大规模上)。
示范。基本概率/比例:
probs <- c(0.1, 0.2, 0.9, 0.32, 0.2, 0.21)
names(probs) <- paste0('b', seq_along(probs))
set.seed(2)
n <- 1e5
dat <- cbind.data.frame(sapply(probs, function(p) {
sample(0:1, size=n, replace=TRUE, prob=c(1-p, p))
}))
head(dat)
# b1 b2 b3 b4 b5 b6
# 1 0 0 1 1 0 1
# 2 0 0 0 1 1 0
# 3 0 0 1 1 0 0
# 4 0 0 1 0 0 0
# 5 1 0 1 0 0 0
# 6 1 0 1 0 1 0
colSums(dat)/n
# b1 b2 b3 b4 b5 b6
# 0.10125 0.20100 0.89975 0.32013 0.20182 0.20827
这看起来是正确的,比例非常接近。现在让我们来看一个较小的人口:
set.seed(2)
n <- 10
dat <- cbind.data.frame(sapply(probs, function(p) {
sample(0:1, size=n, replace=TRUE, prob=c(1-p, p))
}))
dat
# b1 b2 b3 b4 b5 b6
# 1 0 0 1 0 1 0
# 2 0 0 1 0 0 0
# 3 0 0 1 1 0 0
# 4 0 0 1 1 0 1
# 5 1 0 1 0 1 0
# 6 1 1 1 0 0 1
# 7 0 1 1 1 1 0
# 8 0 0 1 0 0 1
# 9 0 0 0 0 0 0
# 10 0 0 1 0 1 0
colSums(dat)/n
# b1 b2 b3 b4 b5 b6
# 0.2 0.2 0.9 0.3 0.4 0.3
即使在四舍五入的情况下,某些列甚至都没有“接近”。这就是问题。为此,我们对随机性的“观点”实际上是“一次一个单元格”,而不是“一次一列”。
好的,让我们一次尝试一列。
set.seed(2)
n <- 10
dat <- cbind.data.frame(sapply(probs, function(p) {
i <- sample(n, size=n*p)
vec <- integer(n)
vec[i] <- 1
vec
}))
dat
# b1 b2 b3 b4 b5 b6
# 1 0 0 1 0 0 0
# 2 1 0 1 1 0 0
# 3 0 0 1 0 0 1
# 4 0 0 0 1 0 0
# 5 0 0 1 0 0 1
# 6 0 1 1 0 0 0
# 7 0 0 1 0 0 0
# 8 0 1 1 1 0 0
# 9 0 0 1 0 1 0
# 10 0 0 1 0 1 0
colSums(dat)/n
# b1 b2 b3 b4 b5 b6
# 0.1 0.2 0.9 0.3 0.2 0.2
在四舍五入中,这看起来更接近。 (您可以选择使用size=ceiling(n*p)
或size=max(1,n*p)
来处理低概率,否则会被截断,而不是舍入。)请注意,如果人口较多,它的行为仍然与上面的实现一样好。< / p>
幸运的是,它们的表现大致相同,所以你可以选择符合你的抽样要求。
library(microbenchmark)
n <- 10
microbenchmark(
probability = cbind.data.frame(sapply(probs, function(p) { sample(0:1, size=n, replace=TRUE, prob=c(1-p, p)) })),
proportion = cbind.data.frame(sapply(probs, function(p) { i <- sample(n, size=n*p); vec <- integer(n); vec[i] <- 1; vec; }))
)
# Unit: microseconds
# expr min lq mean median uq max neval
# probability 99.191 104.6620 126.0461 114.5075 139.4880 384.001 100
# proportion 106.485 113.2315 131.9465 122.7135 149.1515 213.334 100
n <- 1e5
...
# Unit: milliseconds
# expr min lq mean median uq max neval
# probability 254.9634 298.0875 349.3892 331.2826 364.0245 680.3098 100
# proportion 281.7271 351.9515 418.4833 386.5976 449.6032 931.0893 100