You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

2023年fitdistrplus拟合截断对数正态分布的失效问题及解决办法

截断对数正态分布拟合失效问题及2023年可行方案

问题背景

尝试为截断数据拟合对数正态分布,参考旧方案后发现失效:truncdist包的dtrunc和ptrunc函数无法通过fitdistrplus的测试函数。

原代码

dtruncated_log_normal <- function(x, a,b, meanlog, sdlog)
  dtrunc(x, "lnorm", a=a, b=b, meanlog=meanlog, sdlog=sdlog)

ptruncated_log_normal <- function(q, a,b, meanlog, sdlog)
  ptrunc(q, "lnorm", a=a, b=b, meanlog=meanlog, sdlog=sdlog)

fit <- fitdist(s, "truncated_log_normal", start=list(a=0.001, b=90, meanlog=mean(log(s)), sdlog=sd(log(s))))

错误信息

Error in fitdist(s, "truncated_log_normal", start = list(a = 0.001, b = 90, :
the function mle failed to estimate the parameters,
with the error code 100
In addition: Warning messages:
1: In fitdist(s, "truncated_log_normal", start = list(a = 0.001, b = 90, :
The dtruncated_log_normal function should return a vector of with NaN values when input has inconsistent values and not raise an error
2: In fitdist(s, "truncated_log_normal", start = list(a = 0.001, b = 90, :
The ptruncated_log_normal function should return a vector of with NaN values when input has inconsistent parameters and not raise an error

数据样本

数据已清理,无异常值、空值或NA,样本如下:

> dput(head(s,150))
c(88.443, 89.296, 89.327, 87.776, 89.405, 89.824, 89.997, 87.678, 
89.665, 88.814, 88.841, 89.728, 89.365, 89.476, 89.189, 88.251, 
88.939, 89.945, 89.567, 89.613, 89.317, 89.622, 87.674, 89.19, 
89.782, 89.891, 89.954, 89.556, 89.093, 89.637, 89.052, 87.395, 
87.835, 89.357, 87.733, 89.459, 88.197, 88.539, 88.564, 87.857, 
88.74, 88.955, 89.691, 88.102, 89.635, 89.116, 89.584, 88.288, 
86.95, 89.182, 89.435, 88.93, 87.567, 89.083, 88.52, 88.897, 
89.54, 88.557, 89.269, 89.854, 89.31, 88.274, 89.126, 89.431, 
88.257, 88.872, 88.978, 89.03, 87.434, 88.305, 89.656, 87.556, 
89.209, 89.508, 87.781, 88.068, 89.933, 87.256, 88.906, 89.067, 
88.92, 87.947, 88.196, 88.951, 89.594, 88.378, 87.482, 88.817, 
89.65, 89.392, 89.932, 87.896, 89.909, 89.265, 89.954, 89.827, 
87.49, 87.786, 89.208, 89.728, 88.905, 87.566, 86.612, 88.363, 
87.457, 87.639, 88.907, 88.425, 87.244, 88.546, 88.221, 89.293, 
87.469, 87.31, 89.107, 88.442, 89.133, 88.812, 88.418, 89.456, 
88.512, 89.514, 87.446, 88.374, 89.282, 87.415, 89.004, 87.627, 
89.107, 89.168, 89.589, 89.288, 88.496, 89.807, 87.518, 88.796, 
88.001, 87.322, 87.353, 88.055, 88.81, 88.456, 87.876, 87.7, 
88.675, 88.996, 89.479, 86.781, 86.928, 87.356)

2023年可行解决办法

方案1:自定义稳健版密度与分布函数

核心问题是旧的自定义函数在参数/输入异常时直接报错,而非返回NaN。修改函数加入错误捕获机制:

library(fitdistrplus)
library(truncdist)

dtruncated_log_normal <- function(x, a, b, meanlog, sdlog) {
  tryCatch(
    dtrunc(x, "lnorm", a = a, b = b, meanlog = meanlog, sdlog = sdlog),
    error = function(e) {
      rep(NaN, length(x))
    }
  )
}

ptruncated_log_normal <- function(q, a, b, meanlog, sdlog) {
  tryCatch(
    ptrunc(q, "lnorm", a = a, b = b, meanlog = meanlog, sdlog = sdlog),
    error = function(e) {
      rep(NaN, length(q))
    }
  )
}

若截断边界a/b是已知固定值,不要将其放入待估参数,固定后仅拟合meanlog和sdlog能大幅提升稳定性:

fixed_a <- min(s)
fixed_b <- 90

fit <- fitdist(s, "truncated_log_normal", 
               start = list(meanlog = mean(log(s)), sdlog = sd(log(s))),
               fix.arg = list(a = fixed_a, b = fixed_b))

方案2:改用bbmle包直接最大化似然函数

跳过fitdistrplus的函数检测,手动构造对数似然函数进行拟合:

library(bbmle)

log_lik_trunc_lnorm <- function(meanlog, sdlog, a, b) {
  sum(dtrunc(s, "lnorm", a = a, b = b, meanlog = meanlog, sdlog = sdlog, log = TRUE))
}

# 若a/b固定,可从参数列表中移除
fit_mle <- mle2(log_lik_trunc_lnorm,
                start = list(meanlog = mean(log(s)), sdlog = sd(log(s)), a = 0.001, b = 90),
                method = "L-BFGS-B")

summary(fit_mle)

方案3:数据转换后拟合标准截断正态分布

观察样本数据为上截断(所有值≤90),可将数据转换为对数形式后拟合截断正态分布,再转换回对数正态参数:

library(truncnorm)

y <- log(s)
fit_truncnorm <- fitdistr(y, "truncnorm", 
                          start = list(a = -Inf, b = log(90), mean = mean(y), sd = sd(y)))

# 转换回对数正态分布参数
lnorm_params <- list(meanlog = fit_truncnorm$estimate["mean"],
                     sdlog = fit_truncnorm$estimate["sd"])

内容的提问来源于stack exchange,提问作者Sol1

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 21:27:05