【问题标题】:Finding mean of standard normal distribution in a given interval求给定区间内标准正态分布的均值
【发布时间】:2023-07-14 14:04:01
【问题描述】:

我想找到给定区间内标准正态分布的平均值。

例如,如果我将标准正态分布一分为二 ([-Inf:0] [0:Inf]),我想得到每一半的平均值。

以下代码几乎完全符合我的要求:

divide <- 2
boundaries <- qnorm(seq(0,1,length.out=divide+1))
t <- sort(rnorm(100000))
means.1 <- rep(NA,divide)
for (i in 1:divide) {
    means.1[i] <- mean(t[(t>boundaries[i])&(t<boundaries[i+1])])
  }    

但我需要一种更精确(和优雅)的方法来计算这些数字(means.1)。

我尝试了以下代码,但没有成功(可能是因为我缺乏概率知识)。

divide <- 2
boundaries <- qnorm(seq(0,1,length.out=divide+1))
means.2 <- rep(NA,divide)
f <- function(x) {x*dnorm(x)}
for (i in 1:divide) {
  means.2[i] <- integrate(f,lower=boundaries[i],upper=boundaries[i+1])$value
}    

有什么想法吗? 提前致谢。

【问题讨论】:

  • 刚刚添加了第二个答案——一个采用完全不同方法的单线。

标签: r mean normal-distribution


【解决方案1】:

问题是 dnorm(x) 在区间(-Inf 到 0)中的积分不是 1,这就是你得到错误答案的原因。要更正,您必须将得到的结果除以 0.5(积分结果)。喜欢:

func <- function(x, ...) x * dnorm(x, ...)
integrate(func, -Inf, 0, mean=0, sd=1)$value / (pnorm(0, mean=0, sd=1) - pnorm(-Inf, mean=0, sd=1)) 

适应不同的间隔应该很容易。

【讨论】:

  • 如果它有一个简短的答案,你能解释为什么你把“...”放在函数中。即为什么是“function(x, ...)”而不是“function(x)”
  • @Hbat ... 允许您将参数通过一个函数传递给另一个函数。在此示例中,... 让 Rcoster 在调用 func 时指定 meansd,即使它们未在定义中命名。只是传递给dnorm(他们的名字)。
【解决方案2】:

感谢您回答我的问题。

根据我的理解,我结合了所有答案:

    divide <- 5
    boundaries <- qnorm(seq(0,1,length.out=divide+1))
# My original thinking        
    t <- sort(rnorm(1e6))
    means.1 <- rep(NA,divide)
    for (i in 1:divide) {
        means.1[i] <- mean(t[((t>boundaries[i])&(t<boundaries[i+1]))])
      }    

# Based on @DWin
    t <- sort(rnorm(1e6))
    means.2 <- tapply(t, findInterval(t, boundaries), mean)

# Based on @Rcoster
    means.3 <- rep(NA,divide)
    f <- function(x, ...) x * dnorm(x, ...)
    for (i in 1:divide) {
      means.3[i] <- integrate(f, boundaries[i], boundaries[i+1])$value / (pnorm(boundaries[i+1]) - pnorm(boundaries[i]))
    }   

# Based on @Kith
    t <- sort(rnorm(1e6))
    means.4 <- rep(NA,divide)    
    for (i in 1:divide) {
      means.4[i] <- fitdistr(t[t > boundaries[i] & t < boundaries[i+1]], densfun="normal")$estimate[1]
    }    

结果

>   means.1
[1] -1.4004895486 -0.5323784986 -0.0002590746  0.5313539906  1.3978177100
>   means.2   
[1] -1.3993590768 -0.5329465789 -0.0002875593  0.5321381745  1.3990997391 
>   means.3
[1] -1.399810e+00 -5.319031e-01  1.389222e-16  5.319031e-01  1.399810e+00
>   means.4
[1] -1.399057073 -0.531946615 -0.000250952  0.531615180  1.400086731

我相信@Rcoster 是我想要的。与我的相比,休息是创新的方法,但仍然是近似的。 谢谢。

【讨论】:

    【解决方案3】:

    您可以结合使用 fitdistr 和向量索引。

    这是一个如何获取正值的均值和标准差的示例:

    library("MASS")
    x = rnorm(10000)
    fitdistr(x[x > 0], densfun="normal")
    

    或者只是区间 (0,2) 中的值:

    fitdistr(x[x > 0 & x < 2], densfun="normal")
    

    【讨论】:

    • 很高兴,确实同意 DWin 的方法:-)
    【解决方案4】:

    假设您的切点是 -1、0、1 和 2,并且您对模拟标准法线的部分的平均值感兴趣。

     samp <-   rnorm(1e5)
     (res <- tapply(samp, findInterval(samp, c( -1, 0, 1, 2)), mean) )
    #         0          1          2          3          4 
    #-1.5164151 -0.4585519  0.4608587  1.3836470  2.3824633 
    

    请注意,标签可以改进。一项改进可能是:

    names(res) <-  paste("[", c(-Inf, -1, 0, 1, 2, Inf)[-6],  " , ", 
                          c(-Inf, -1, 0, 1, 2, Inf)[-1], ")", sep="")
    > res
    [-Inf , -1)    [-1 , 0)     [0 , 1)     [1 , 2)   [2 , Inf) 
     -1.5278185  -0.4623743   0.4621885   1.3834442   2.3835116 
    

    【讨论】:

    • 似乎不同意 @Josh 解决方案?
    • @Carl -- 我更相信模拟结果而不是我想出的结果,所以我删除了我的答案。不过,还没有弄清楚为什么以常规分位数间隔评估点不起作用。
    • 把我逗乐了。乔什认为他更尊重数据而不是理论。当此方法重复应用于范围 [0,1) 的 1e5 大小的样本时,0.423 的值似乎不在可信的值范围内。真实值为 0.4598622。
    • @DWin -- 谢谢你的好话。回家的路上,我发现了我之前的错误,并更正了帖子。有这么多的眼球仔细检查发布在这里的想法真是太好了。
    【解决方案5】:

    使用 distrExdistr 包:

    library(distrEx)
    E(Truncate(Norm(mean=0, sd=1), lower=0, upper=Inf))
    # [1] 0.797884
    

    (请参阅 distrDoc 包中的 vignette(distr) 以了解 distr 套件和相关包的出色概述。)


    或者,仅使用基数 R,这是一个替代方案,它在 lbub 之间的区间内构造期望的离散近似值。调整近似矩形的底边,使它们的面积都相等(即,一个点落在每个矩形中的概率相同)。

    intervalMean <- function(lb, ub, n=1e5, ...) {
        ## Get x-values at n evenly-spaced quantiles between lower and upper bounds
        xx <- qnorm(seq(pnorm(lb, ...), pnorm(ub, ...), length = n), ...)
        ## Calculate expectation
        mean(xx[is.finite(xx)])
    }
    
    ## Your example
    intervalMean(lb=0, ub=1)
    # [1] 0.4598626
    
    ## The mean of the complete normal distribution
    intervalMean(-Inf, Inf)
    ## [1] -6.141351e-17
    
    ## Right half of standard normal distribution
    intervalMean(lb=0, ub=Inf)
    # [1] 0.7978606
    
    ## Right half of normal distribution with mean 0 and standard deviation 100
    intervalMean(lb=0, ub=Inf, mean=0, sd=100)
    # [1] 79.78606
    

    【讨论】:

    • @CarlWitthoft -- 检查最后一次调用中的界限:标准差为 100 的正态分布的右半部分应该的期望值是右半部分的 100 倍标准正态分布。
    • 好的,这是我的困惑。我们正在计算x 的值,它对应于区间的平均值。 x 超过 -Inf,Inf 的最可能值为零。但这不是分布本身的平均值 ("y= exp(x^2/sigma^2))。
    • @CarlWitthoft -- Does this image, from Wikipedia's 'expected value' page, help? 当我们查看(标准)正态分布的右半部分时,支点处于正值。当我们只看左半边时,支点将为负值(大小相同)。
    • @CarlWitthoft -- 好的,我现在已经修好了,如果你(或其他任何人)有兴趣,我就把它揭开。我之前提出的解决方案系统地低估了尾巴的贡献。
    最近更新 更多