如何用fitdistr或fitdistrplus从截断数据恢复原正态分布参数?
拟合截断数据以恢复原始正态分布参数
直接用fitdistr拟合得到的不是原始N(3,1)的参数,是因为它默认拟合的是未截断的正态分布,而你的数据是原分布截断到x≤2后的样本,自然会得到截断后分布的均值和标准差(也就是你看到的1.48和0.43左右)。要恢复原始分布参数,必须告诉拟合函数数据是截断的,两种方法可以实现:
方法一:用MASS::fitdistr自定义截断正态密度函数
我们需要手动构造截断正态的对数似然函数,让拟合过程考虑截断条件:
library(MASS) # 生成截断数据 N <- 10000 trunc <- rnorm(N, mean = 3, sd = 1) trunc <- trunc[trunc <= 2] # 定义截断正态的对数密度函数(截断上限为2) dnorm_trunc_log <- function(x, mean, sd) { # 原始正态密度的对数,减去截断点的累积概率对数,得到截断分布的对数密度 log(dnorm(x, mean, sd)) - log(pnorm(2, mean, sd)) } # 拟合,设置合理初始值 fit_result <- fitdistr(trunc, densfun = dnorm_trunc_log, start = list(mean = 2, sd = 1)) print(fit_result)
运行后你会发现拟合出的均值和标准差会接近原始的3和1,因为我们在似然计算中加入了截断的校正项。
方法二:用fitdistrplus便捷拟合截断分布
fitdistrplus包专门针对分布拟合做了扩展,支持直接指定截断范围,不需要手动写密度函数:
library(fitdistrplus) # 生成截断数据 N <- 10000 trunc <- rnorm(N, mean = 3, sd = 1) trunc <- trunc[trunc <= 2] # 拟合截断正态分布,指定截断上限为2 fit_result <- fitdist(trunc, distr = "norm", method = "mle", fix.arg = list(upper = 2), start = list(mean = 2, sd = 1)) summary(fit_result)
fix.arg参数明确告诉函数数据是从正态分布截断到x≤2的样本,拟合过程会自动校正似然,得到接近原始参数的结果。
关键注意点
- 初始值要合理:如果初始值和真实参数相差太大,可能导致拟合不收敛,建议根据数据的大致范围设置(比如示例中用mean=2、sd=1作为初始值)。
- 样本量足够:你的示例中截断后样本量约1500+,已经足够让拟合结果接近真实参数,样本量越大精度越高。
内容的提问来源于stack exchange,提问作者vtuna
相关产品推荐
相关产品推荐

