从R中未知密度的分位数生成随机样本

时间:2013-12-11 00:44:04

标签: r

如何从R中f(x)x之间0的未知密度4的分位数生成随机样本数据?

     f = function(x) ((x-1)^2) * exp(-(x^3/3-2*x^2/2+x))

3 个答案:

答案 0 :(得分:5)

如果我理解正确(??),您希望生成随密度函数由f(x)给出的分布的随机样本。一种方法是从均匀分布U[0,1]生成随机样本,然后将此样本转换为密度。这是使用f的逆cdf完成的,这是前面已经描述过的方法here

所以,让

f(x)     = your density function, 
F(x)     = cdf of f(x), and 
F.inv(y) = inverse cdf of f(x).

在R代码中:

f <- function(x) {((x-1)^2) * exp(-(x^3/3-2*x^2/2+x))}
F <- function(x) {integrate(f,0,x)$value}
F <- Vectorize(F)

F.inv <- function(y){uniroot(function(x){F(x)-y},interval=c(0,10))$root}
F.inv <- Vectorize(F.inv)

x <- seq(0,5,length.out=1000)
y <- seq(0,1,length.out=1000)

par(mfrow=c(1,3))
plot(x,f(x),type="l",main="f(x)")
plot(x,F(x),type="l",main="CDF of f(x)")
plot(y,F.inv(y),type="l",main="Inverse CDF of f(x)")

在上面的代码中,由于f(x)仅在[0,Inf]上定义,因此我们将F(x)计算为f(x)从0到x的积分。然后我们使用uniroot(...)上的F-y函数将其反转。需要使用Vectorize(...)因为,与几乎所有R函数不同,integrate(...)uniroot(...)不对向量进行操作。您应该查看这些函数的帮助文件以获取更多信息。

现在我们只生成一个从X中抽取的随机样本U[0,1]并将其转换为Z = F.inv(X)

X <- runif(1000,0,1)   # random sample from U[0,1]
Z <- F.inv(X)

最后,我们证明Z确实分发为f(x)

par(mfrow=c(1,2))
plot(x,f(x),type="l",main="Density function")
hist(Z, breaks=20, xlim=c(0,5))

答案 1 :(得分:2)

拒绝抽样很容易:

   drawF <- function(n) {  
     f <- function(x) ((x-1)^2) * exp(-(x^3/3-2*x^2/2+x))
     x <- runif(n, 0 ,4)
     z <- runif(n) 
     subset(x, z < f(x)) # Rejection
   }

不是最有效率的,但它可以完成工作。

答案 2 :(得分:0)

使用sample。从现有函数f生成概率向量,正确归一化。从帮助页面:

sample(x, size, replace = FALSE, prob = NULL)


Arguments

x       Either a vector of one or more elements from which to choose, or a positive integer. See ‘Details.’

n    a positive number, the number of items to choose from. See ‘Details.’

size    a non-negative integer giving the number of items to choose.

replace    Should sampling be with replacement?

prob    A vector of probability weights for obtaining the elements of the vector being sampled.