找出给定区间内标准正态分布的均值

时间:2013-04-12 17:21:13

标签: r mean normal-distribution

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

例如,如果我将标准正态分布分成两个([ - 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])])
  }    

但我需要一种更精确(优雅)的方法来计算这些数字(均值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
}    

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

5 个答案:

答案 0 :(得分:3)

问题是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)) 

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

答案 1 :(得分:2)

您可以使用fitdistr和矢量索引的组合。

以下是如何获得正值的均值和标准的示例:

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

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

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

答案 2 :(得分:2)

假设你的分界点是-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 

答案 3 :(得分: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就是我想要的那个。休息是与我相比的创新方法,但仍然是近似的。 感谢。

答案 4 :(得分:1)

使用 distrEx distr 套餐:

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