Henry,正如 cmets 中所建议的,有两种生成此类数据的一般方法。一种是计算“每个单元格为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) 来处理低概率,否则它会被截断,而不是四舍五入。)请注意,对于更大的人口,它的行为仍然与上述实现一样。
幸运的是,它们的性能大致相同,因此您可以选择满足您的采样要求的任何一个。
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