对称分布
尽管OP的例子是不完全对称,这是足够接近 - 并从那里开始有用的,因为该解决方案是简单得多。可以使用integrate
和optimize
的组合。我将其作为自定义函数编写,但请注意,如果在其他情况下使用此函数,则可能需要重新考虑搜索分位数的界限。
# For a distribution with a single peak, find the symmetric!
# interval that contains probs probability. Search over 'range'.
f_quan <- function(fun, probs, range=c(0,1)){
mode <- optimize(fun, interval = range, maximum = TRUE, tol = 1e-12)[[1]]
total_area <- integrate(fun, range[1], range[2])[[1]]
O <- function(d){
parea <- integrate(fun, mode-d, mode+d)[[1]]/total_area
(probs - parea)^2
}
# Bounds for searching may need some adjustment depending on the problem!
o <- optimize(O, c(0,range[2]/2 - 1E-02))[[1]]
return(c(mode-o, mode+o))
}
使用它像这样,
f <- f_quan(posterior, 0.95)
curve(posterior, n = 1e4)
abline(v=f, col="blue", lwd=2, lty=3)
给
不对称分布
在非对称分布的情况下,我们必须寻找两点符合标准P(a < x < b)= Prob,其中Prob是一些期望的概率。由于存在无限多的间隔(a,b),OP建议找到最短的一个。
解决方案中重要的是我们要搜索的区域domain
的定义(我们不能使用-Inf, Inf
,因此用户必须将其设置为合理的值)。
# consider interval (a,b) on the x-axis
# integrate our function, normalize to total area, to
# get the total probability in the interval
prob_ab <- function(fun, a, b, domain){
totarea <- integrate(fun, domain[1], domain[2])[[1]]
integrate(fun, a, b)[[1]]/totarea
}
# now given a and the probability, invert to find b
invert_prob_ab <- function(fun, a, prob, domain){
O <- function(b, fun, a, prob){
(prob_ab(fun, a, b, domain=domain) - prob)^2
}
b <- optimize(O, c(a, domain[2]), a = a, fun=fun, prob=prob)$minimum
return(b)
}
# now find the shortest interval by varying a
# Simplification: don't search past the mode, otherwise getting close
# to the right-hand side of domain will give serious trouble!
prob_int_shortest <- function(fun, prob, domain){
mode <- optimize(fun, interval = domain, maximum = TRUE, tol = 1e-12)[[1]]
# objective function to be minimized: the width of the interval
O <- function(a, fun, prob, domain){
b <- invert_prob_ab(fun, a, prob, domain)
b - a
}
# shortest interval that meets criterium
abest <- optimize(O, c(0,mode), fun=fun, prob=prob, domain=domain)$minimum
# now return the interval
b <- invert_prob_ab(fun, abest, prob, domain)
return(c(abest,b))
}
现在使用上面的代码。我使用非常不对称的函数(假设mydist实际上是一些复杂的pdf,而不是dgamma)。
mydist <- function(x)dgamma(x, shape=2)
curve(mydist(x), from=0, to=10)
abline(v=prob_int_shortest(mydist, 0.9, c(0,10)), lty=3, col="blue", lwd=2)
在这个例子中我设置域至(0,10),由于显然的间隔必须在某处。请注意,使用非常大的值(例如(0,1E05))不起作用,因为integrate
在接近零的长序列时遇到问题。再次,对于你的情况,你将不得不调整域名(除非有人有更好的主意!)。
界限是问题:如果你搜索整个域(在你的案例中为0-1),我们会遇到问题,因为函数没有定义在0或1(但它在附近)。在函数d中,距离模式的距离是变化的,以便找到(模式-d)到(模式+ d)的积分等于请求的概率(在你的情况下为0.95)的d。因此,这只适用于对称函数,否则你必须优化两个参数。 –
我认为如果它是不对称的,这个问题不会有单一的解决方案!你可以找到许多可以整合到一定概率的pdf的间隔。或者,你实际上是在寻找2.5%和97.%的分位数(这些分位数会整合到95%之间)?如果是这样,那可以做到。 –
这是可以做到的 - 但请注意,与您提出的原始问题完全不同!我毫不犹豫地编辑我的帖子,因为这本身就是有用的。我可能会添加另一个答案。 –