基于密度函数与qnorm的正态分布分位数估计问题咨询
解决分位数估计偏差的问题
嘿,我懂你为啥头疼了——你这儿踩了个超容易犯的小误区!咱们来一步步把问题掰明白:
问题出在哪儿?
你用quantile(density(data)$x, probs = 0.997)来计算分位数的思路完全错了!density(data)$x只是密度估计函数生成的横轴坐标点,这些点是用来绘制密度曲线的辅助值,根本不是你的原始样本数据。用分位数函数去计算这些坐标点的分位数,和你真正想要的「样本的99.7%分位数」完全不是一回事,这就是为啥两个结果差了近200的原因。
正确的做法有两种:
1. 直接用原始样本计算分位数
这是最直接也最准确的方式,因为你的样本量很大(10000个),样本分位数会非常接近理论分位数:
set.seed(1234) data<-rnorm(10000,1800,150) hist(data,probability = TRUE,xlim=c(500,3000)) lines(density(data),col="red") # 理论分位数 q1<-qnorm(.997,mean = 1800,sd=150,lower.tail = TRUE) # 样本分位数(正确姿势) q2<-quantile(data,probs = 0.997) q1 q2 abline(v=q1,col="blue",lwd=2) abline(v=q2,col="green",lwd=2,lty=2) legend("topright", legend=c("理论分位数","样本分位数"), col=c("blue","green"), lwd=2, lty=c(1,2))
运行后你会发现,q1和q2的差值会非常小,完全在合理范围内。
2. 通过密度曲线估计分位数(进阶方法)
如果你非要基于密度曲线来计算分位数,需要先通过密度的积分得到近似的累积分布函数(CDF),再找到使得累积概率达到0.997的x值:
set.seed(1234) data<-rnorm(10000,1800,150) hist(data,probability = TRUE,xlim=c(500,3000)) dens <- density(data) lines(dens,col="red") # 理论分位数 q1<-qnorm(.997,mean = 1800,sd=150,lower.tail = TRUE) # 基于密度曲线的分位数估计 cdf <- approxfun(dens$x, cumsum(dens$y * diff(dens$x)[1]), method = "linear") q2_dens <- uniroot(function(x) cdf(x) - 0.997, interval = range(dens$x))$root q1 q2_dens abline(v=q1,col="blue",lwd=2) abline(v=q2_dens,col="purple",lwd=2,lty=3) legend("topright", legend=c("理论分位数","密度估计分位数"), col=c("blue","purple"), lwd=2, lty=c(1,3))
这个方法得到的结果也会和理论值非常接近,适合你需要基于密度分布做估计的场景。
总结
核心错误就是把密度曲线的横轴坐标点当成了原始样本数据——记住,分位数是针对样本数据或者分布的CDF来计算的,不是针对密度曲线的x轴点哦!
内容的提问来源于stack exchange,提问作者user3483060
相关产品推荐
相关产品推荐

