我想在给定的时间间隔内找到标准正态分布的平均值。
例如,如果我将标准正态分布分成两个([ - 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
}
有什么想法吗? 提前致谢。
答案 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,这是在lb
和ub
之间的区间内构建期望的离散近似的替代方案。调整近似矩形的基数,使它们都具有相等的面积(即使每个点中落点的概率相同)。
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