【问题标题】:sampling data based on posterior joint-probabilities基于后验联合概率的采样数据
【发布时间】:2018-07-03 14:10:32
【问题描述】:

我有一个数据集,并希望根据我手动设置的概率获得一个样本。

例子:(id = user, score(sort by desc), b1-b6(dummy variable)),1代表用户有这个特征,否则为0

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 值

任何想法都将不胜感激

更新 它是从遵循分布(p1、p2 等)的大型数据集(1000k 中的 1k 样本)中抽取样本,而不是模拟虚假数据

方法一:可以通过重复随机抽样来解决。并使用最接近的(需要重新采样或迭代技巧)。

方法二:使用线性优化算法(可能比较复杂,有2^6种可能,需要求解大方程)

【问题讨论】:

  • 您不能只对b 向量和cbind 它们进行采样吗?
  • as.numeric(sapply(c(0.1, 0.2, 0.9, 0.32, 0.2, 0.21), rbernoulli, n = 1))
  • @RobJensen 不是基础 R,什么包?为什么不基地?
  • purrr 包,见??rbernoulli
  • 没有注意到 rbernoulli 不是基本 R 或 stats 函数。你也可以sapply(c(0.1, 0.2, 0.9, 0.32, 0.2, 0.21), rbinom, size = 1, n = 1)

标签: python r random statistics probability


【解决方案1】:

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

【讨论】:

  • 演示旨在模拟新数据。但是,我期望的是从现有数据集中获取样本。也就是说,它具有关于 b1-b6 的先验概率(先验:p1 = 0.2,p2 = 0.3,我想得到一个具有后验概率的样本:p1 = 0.3,p2 = 0.5 等)。很抱歉造成混乱,我没有注意到这种差异。感谢@MrSmithGoesToWashington 指出这一点
猜你喜欢
  • 1970-01-01
  • 2011-09-02
  • 1970-01-01
  • 2015-05-03
  • 1970-01-01
  • 2016-05-21
  • 2010-10-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多