如何从R中f(x)
和x
之间0
的未知密度4
的分位数生成随机样本数据?
f = function(x) ((x-1)^2) * exp(-(x^3/3-2*x^2/2+x))
答案 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.