R语言拟合多类截断概率分布时如何避免代码重复
多截断分布批量拟合通用实现
核心实现逻辑是利用R的do.call机制动态传递分布参数,避免为每个分布硬编码参数名,仅需一次性配置各分布的参数规则即可完成批量拟合,完全消除重复代码。
基础依赖函数
首先保留Nadarajah和Kotz提出的截断分位数计算函数:
qtrunc <- function(p, spec, a = -Inf, b = Inf, ...) { tt <- p G <- get(paste("p", spec, sep = ""), mode = "function") Gin <- get(paste("q", spec, sep = ""), mode = "function") tt <- Gin(G(a, ...) + p*(G(b, ...) - G(a, ...)), ...) return(tt) }
通用拟合损失函数
编写通用损失函数,不需要绑定任何特定分布的参数名,运行时动态接收参数名配置完成分位数计算和距离度量:
fit_spec <- function(x, spec, param_names, l = -Inf, h = Inf, target_probs, target_qs) { # 将优化器传入的无名称参数向量转为对应分布的命名参数列表 dist_params <- setNames(as.list(x), param_names) # 批量计算所有目标概率点对应的截断分布分位数 calc_quantiles <- vapply(target_probs, function(p) { do.call(qtrunc, c(list(p = p, spec = spec, a = l, b = h), dist_params)) }, numeric(1)) # 返回分位数残差的均方根作为优化目标值 sqrt(sum((target_qs - calc_quantiles)^2)) }
批量拟合使用方法
步骤1:配置待拟合分布规则
仅需为每个待拟合的分布配置一次参数信息,后续新增分布也只需在此列表追加条目即可,无需修改核心函数:
dist_config <- list( gamma = list( param_names = c("shape", "rate"), # 分布的参数名,顺序和优化参数向量对应 init_par = c(2, 4), # 优化初始值 lower_bound = c(1.01, 1.4) # 参数下界 ), norm = list( param_names = c("mean", "sd"), init_par = c(10, 5), lower_bound = c(-Inf, 0.01) # 正态分布标准差必须大于0 ), lnorm = list( param_names = c("meanlog", "sdlog"), init_par = c(2, 1), lower_bound = c(-Inf, 0.01) ) # 可继续追加weibull、exp等其他R原生支持的分布配置 )
步骤2:设置公共拟合条件
固定所有分布共用的截断边界、目标分位点概率、观测分位数值:
# 截断上下限 trunc_lower <- 0 trunc_upper <- 20 # 目标分位点对应概率 prob_points <- c(1/3, 2/3) # 观测到的对应分位数值 obs_quantiles <- c(5, 13)
步骤3:批量执行拟合
一次性完成所有配置分布的参数优化,无需为每个分布单独写调用逻辑:
fit_results <- lapply(names(dist_config), function(dist_name) { current_cfg <- dist_config[[dist_name]] optim( par = current_cfg$init_par, fn = fit_spec, spec = dist_name, param_names = current_cfg$param_names, l = trunc_lower, h = trunc_upper, target_probs = prob_points, target_qs = obs_quantiles, method = "L-BFGS-B", lower = current_cfg$lower_bound ) }) # 绑定分布名方便结果索引 names(fit_results) <- names(dist_config)
扩展说明
- 该实现支持任意数量的分位点拟合,只需调整
prob_points和obs_quantiles传入等长的向量即可,不需要修改核心函数 - 所有分布共用完全一致的距离计算逻辑,避免重复编码带来的人为错误
- 适配所有R中内置
p*、q*函数的标准分布,无需额外适配代码
内容的提问来源于stack exchange,提问作者JeremyC
相关产品推荐
相关产品推荐

