我遇到了一个乍一看似乎根本没有问题的问题。
我想编写一个函数,它将接受分布名称和参数作为参数,并返回给定分布的期望值。在我的代码中,我将使用参数 alpha = 0.2 和 beta = 0.3 的 Beta 分布。该分布的期望值为:0.2 / (0.2 + 0.3) = 0.2 / 0.5 = 0.4
最简单的方法似乎是采样:
estimatedExpectedValue <- function(distribution, parameters) {
do.call(get(paste0("r",distribution)), as.list(c(10000, parameters))) %>% mean
}
estimatedExpectedValue("beta",c(0.2,0.3))
[1] 0.4006945
虽然这很容易实现,但样本均值“只是”期望值的最大似然估计,因此它总是存在一些误差。这取决于上下文,无论这是否重要。
那么我们也知道期望值的定义是:
...其中 f(x) 是密度函数,在 R 中我们可以进行数值积分,因此:
expectedValueFromIntegration <- function(distribution, parameters) {
fnToBeIntegrated <- Vectorize(
function(x) {x * do.call(get(paste0("d",distribution)), as.list(c(x, parameters)))},
vectorize.args = c("x"))
integrate(fnToBeIntegrated, lower = -Inf, upper = Inf)
}
expectedValueFromIntegration("beta",c(0.2,0.3))
Error in integrate(fnToBeIntegrated, lower = -Inf, upper = Inf) :
non-finite function value
但是,正如您所看到的,由于某种原因,dbeta 在某些时候给出了 NaN,而集成函数不喜欢它。我很清楚 Beta 分布的支持度从 0 开始,到 1 结束,但是在支持度之外密度应该为 0,并且从数学上来说,对于任何分布(即使对于离散分布)来说,一切都应该很好,如果我们只是在实轴上积分。
但是在 R 中,如果我集成支持,它就会起作用:
expectedValueFromIntegration <- function(distribution, parameters) {
fnToBeIntegrated <- Vectorize(
function(x) {x * do.call(get(paste0("d",distribution)), as.list(c(x, parameters)))},
vectorize.args = c("x"))
integrate(fnToBeIntegrated, lower = 0, upper = 1)
}
expectedValueFromIntegration("beta",c(0.2,0.3))
0.4 with absolute error < 1.9e-05
但是,现在我需要知道(即输入)对发行版的支持,或者至少创建某种查找表,因为据我了解,R 没有存储在任何地方的不同发行版的支持信息,对吗?
还有第三种方法吗?我正在寻找一种通用的方法来做到这一点,因为我不喜欢使用 ifelse 结构,并且对每个发行版使用不同的方法。
如果需要分布的支持,可以使用
q*
(分位数函数)来求解支持,指定c(0,1)
为分位数。
下面只是一些示例来给您提供想法,您可以根据您的编码风格进行自定义
# support of beta distribution
> qbeta(0:1, 0.2, 0.3)
[1] 0 1
# support of gamma distribution
> qgamma(0:1, 0.2)
[1] 0 Inf
# support of norm distribution
> qnorm(0:1)
[1] -Inf Inf