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

非线性混合效应模型的Bootstrap置信区间获取与绘图问题

非线性混合效应模型(Gompertz)Bootstrap置信区间问题

问题概述

使用lme4包的nlmer()构建带固定渐近线的Gompertz非线性混合效应模型,模型本身收敛正常,但无法获取Bootstrap置信区间用于geom_ribbon()绘制曲线置信区间:

  • 调用confint()时报错:Error: step factor reduced below 0.001 without reducing pwrss
  • 调用bootMer()时报错:Error in model.matrix.default(eval(substitute(~foo, list(foo = x[[2]]))), : model frame and formula mismatch in model.matrix()

示例数据

# 创建结构相似的示例数据
x_data <- seq(1, 14, length.out = 200)
y_data <- 53 * exp(-exp(-0.14 *(x_data - 13))) + rnorm(length(x_data), mean = 0, sd = 0.5)
individ_ID <- c(1:200) # 个体ID
group_ID <- c(1:10) # 组ID 
group_ID2 <- rep(group_ID, each = 4)
mydata1 <- data.frame(x_data, y_data, individ_ID, group_ID2)

x_data <- seq(15, 28, length.out = 200)
y_data <- 53 * exp(-exp(-0.14 *(x_data - 13))) + rnorm(length(x_data), mean = 0, sd = 0.5)
individ_ID <- c(1:200)
group_ID <- c(1:10)
group_ID2 <- rep(group_ID, each = 4)
mydata2 <- data.frame(x_data, y_data, individ_ID, group_ID2)

mydata3 <- rbind(mydata1, mydata2)

模型构建代码

# 定义Gompertz模型函数(固定渐近线A=53)
gompertz_pp <- ~53*exp(-exp(-k*(d - Ti)))

# 生成带导数的模型函数,用于nlmer拟合
fn.gompertz.pp <- deriv(gompertz_pp,
                        namevec=c("k","Ti"), 
                        function.arg=c("d","k","Ti"))

# 设置初始值
startvec <- c(k = 0.15, Ti = 12)

# 拟合非线性混合效应模型
mod <- nlmer(y_data ~ fn.gompertz.pp(x_data, k, Ti) ~ (Ti|group_ID2/individ_ID) + (k|group_ID2/individ_ID), 
             data = mydata3, start = startvec)

解决方案

1. 修正bootMer()调用方式

非线性混合模型使用bootMer()时,直接传入fixef作为FUN可能触发公式匹配错误,需自定义FUN函数,并选择参数化Bootstrap(比非参数化更稳定):

# 自定义Bootstrap函数,返回固定效应参数
boot_fun <- function(model) {
  return(fixef(model))
}

# 运行参数化Bootstrap,设置并行加速(可选)
library(parallel)
boot_result <- bootMer(mod, FUN = boot_fun, nsim = 100, type = "parametric",
                       parallel = "multicore", ncpus = detectCores()-1)

# 提取Bootstrap置信区间
boot_ci <- confint(boot_result, level = 0.95)

2. 优化confint()拟合稳定性

confint()报错是因为Bootstrap迭代中部分模型拟合失败,可通过更换优化器、增加迭代次数解决:

# 重新拟合模型,指定更稳定的优化器
mod_optim <- nlmer(y_data ~ fn.gompertz.pp(x_data, k, Ti) ~ (Ti|group_ID2/individ_ID) + (k|group_ID2/individ_ID), 
                   data = mydata3, start = startvec,
                   control = nlmerControl(optimizer = "optimx", 
                                          optCtrl = list(method = "L-BFGS-B", maxit = 1000)))

# 调用confint进行Bootstrap
confint_ci <- confint(mod_optim, method = "boot", nsim = 100, 
                      parallel = "multicore", ncpus = detectCores()-1)

3. 基于参数抽样的替代置信区间方法

如果Bootstrap始终失败,可通过从固定效应协方差矩阵中抽样参数,结合模型生成预测值的分布来计算置信区间:

library(MASS)
library(dplyr)
library(ggplot2)

# 提取固定效应估计值和协方差矩阵
fixef_vals <- fixef(mod)
vcov_mat <- vcov(mod)

# 从多元正态分布中抽样参数(1000次)
set.seed(123)
param_samples <- MASS::mvrnorm(n = 1000, mu = fixef_vals, Sigma = vcov_mat)

# 生成用于预测的x序列
new_x <- seq(min(mydata3$x_data), max(mydata3$x_data), length.out = 100)

# 生成所有抽样参数对应的预测值
pred_df <- expand.grid(x = new_x, sample_id = 1:1000)
pred_df$y_pred <- apply(pred_df, 1, function(row) {
  k_val <- param_samples[row["sample_id"], "k"]
  ti_val <- param_samples[row["sample_id"], "Ti"]
  # 代入Gompertz模型计算预测值
  53 * exp(-exp(-k_val*(row["x"] - ti_val)))
})

# 计算每个x点的95%置信区间
ci_df <- pred_df %>%
  group_by(x) %>%
  summarise(
    fit = mean(y_pred),
    lower_ci = quantile(y_pred, 0.025),
    upper_ci = quantile(y_pred, 0.975)
  )

# 绘制原始数据、拟合曲线和置信区间
ggplot() +
  geom_point(data = mydata3, aes(x = x_data, y = y_data), alpha = 0.3, size = 0.8) +
  geom_line(data = ci_df, aes(x = x, y = fit), color = "#E63946", linewidth = 1) +
  geom_ribbon(data = ci_df, aes(x = x, ymin = lower_ci, ymax = upper_ci), 
              fill = "#E63946", alpha = 0.2) +
  labs(x = "x", y = "y") +
  theme_minimal()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 01:15:05