从概率密度分布生成数据

13

假设我有一个简单的数组,其对应的概率分布如下。

library(stats)    
data <- c(0,0.08,0.15,0.28,0.90)
pdf_of_data <- density(data, from= 0, to=1, bw=0.1)

有没有方法可以使用相同的分布生成另一组数据。由于操作是概率性的,因此它不必完全匹配初始分布,但将仅从该分布中生成。

我自己成功找到了一个简单的解决方案。谢谢!

3个回答

11

你最好生成经验累积密度函数,近似求逆,并转换输入。

复合表达式看起来像

random.points <- approx(
  cumsum(pdf_of_data$y)/sum(pdf_of_data$y),
  pdf_of_data$x,
  runif(10000)
)$y

产量

hist(random.points, 100)

输入图片说明


太好了!谢谢你! - puslet88
2
这是一个非常棒的答案!我将把它添加到“stackoverflow”包中。 - Neal Fultz
你可能想看一下 ecdf 函数。它可以为你完成大部分工作。 - IRTFM
1
@42- 我不认为 ecdf 函数在这种情况下有什么帮助。我们有一个概率密度函数,可以使用 cumsum 计算出累积分布函数,然后再将其反转以获取分位函数,并从中进行绘制。ecdf 生成一个来自分布的数据的累积分布函数。 - user295691

9

?density的文档示例中,你(几乎)可以得到答案。

因此,像这样的内容应该可以解决问题:

library("stats")    
data <- c(0,0.08,0.15,0.28,0.90)
pdf_of_data <- density(data, from= 0, to=1, bw=0.1)

# From the example.
N <- 1e6
x.new <- rnorm(N, sample(data, size = N, replace = TRUE), pdf_of_data$bw)

# Histogram of the draws with the distribution superimposed.
hist(x.new, freq = FALSE)
lines(pdf_of_data)

Imgur

你可以像拒绝采样中所述一样拒绝区间外的抽样。 或者,你可以使用链接中描述的算法。

3
这不只是向数据中添加高斯噪声,而不是从平滑的密度曲线中绘制数据吗? - Neal Fultz
1
@NealFultz 记住,平滑密度曲线是高斯分布的混合物-每个观察结果都有一个。因此,我们只是直接从每个组件中进行采样。但是,你也是正确的。 - Anders Ellern Bilgrau
@NealFultz 对的。但是我猜只要使用正确的函数而不是 rnorm,它就很容易被修改。 - Anders Ellern Bilgrau
谢谢,这真的很棒!我猜反向抽样看起来应该像这样:expected_sample_size <- 2; new_sample <- list(); while(length(new_sample) < expected_sample_size ){ new_item <- rnorm(1, sample(data, size = 1, replace = TRUE), data_pdf$bw); if(new_item >0 & new_item < 1){ new_sample[length(new_sample)+1] <- new_item} } - puslet88
使用这种方法还有一个限制,即如果原始分布预测某个数字的概率为0,那么新样本可能仍包含该数字,因为变异是在概率密度分布之后添加的。我觉得。 - puslet88

4
从曲线中提取数据:
sample(pdf_of_data$x, 1e6, TRUE, pdf_of_data$y)

4
请注意,此方法强烈依赖于density中的n参数。您最多只能获得n个唯一值。您只是从具有n个值和相应概率的离散概率函数中进行抽样。根据您的应用程序,这可能完全可以接受。 - Anders Ellern Bilgrau
这是一个很好的观点,n可能被操纵以适应数据。对于我的目的来说,这实际上也可以。这里有太多正确和有用的答案可供选择了。再次感谢! - puslet88

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接