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

如何在nlme非线性混合效应模型中计算杠杆值与Cook距离?

在nlme模型中计算杠杆值与Cook距离的解决方案

问题背景

使用nlme包构建非线性混合效应模型后,计算杠杆值和Cook距离时出现以下报错:

杠杆值计算报错

执行lev<-hat(model.matrix(model))时触发:

Error in x$terms %||% attr(x, "terms") %||% stop("no terms component nor attribute") : no terms component nor attribute

Cook距离计算报错

执行cd<-cooks.distance(model)时触发:

Error in cooks.distance.lme(model) : not implemented for "nlme" objects"

模型代码如下:

formula = log_Lobs ~ log(150*((1 + ((150/Lt_1)^(1/exp(p))-1)*exp(-exp(k)*td/365))^(-exp(p))))
model <- do.call(nlme,
                    list(formula,
                         fixed = c(p ~ 1, k ~ 1 + season2),
                         random = k ~ 1 | id,
                         data = data_select,
                         start = list(fixed = c(p, k)),
                         na.action = na.exclude,
                         control=list(maxIter=1e6, msMaxIter = 1e6, msVerbose = TRUE)
                    ))

解决方案

一、计算杠杆值

nlme模型的model.matrix()返回对象不包含terms属性,无法直接用hat()处理。可通过两种方式计算:

方法1:基于固定效应设计矩阵

提取固定效应的设计矩阵,结合协方差矩阵构建投影矩阵计算杠杆值:

# 提取固定效应设计矩阵
X <- model.matrix(model, type = "fixed")
# 计算杠杆值
lev <- hat(t(X) %*% solve(vcov(model)) %*% X) / nrow(X)

方法2:基于模型预测矩阵

利用nlme模型内置的预测矩阵(predMatrix)计算,更适配非线性混合效应模型场景:

# 获取模型预测矩阵
P <- model$predMatrix
# 计算杠杆值
lev <- diag(P %*% t(P))

二、计算Cook距离

nlme未内置Cook距离计算函数,可通过两种方式实现:

方法1:基于残差与杠杆值的公式计算

Cook距离核心公式为:$D_i = \frac{r_i^2}{p} \times \frac{h_{ii}}{1 - h_{ii}}$,其中$r_i$为标准化残差,$h_{ii}$为杠杆值,$p$为固定效应参数个数。代码实现:

# 获取皮尔逊标准化残差
res <- residuals(model, type = "pearson")
# 计算杠杆值(用方法1或2均可)
X <- model.matrix(model, type = "fixed")
lev <- hat(t(X) %*% solve(vcov(model)) %*% X) / nrow(X)
# 获取固定效应参数数量
p <- length(fixef(model))
# 计算Cook距离
cd <- (res^2 / p) * (lev / (1 - lev))

方法2:逐观测删除重拟合计算

通过循环删除每个观测后重新拟合模型,计算参数估计的变化程度(适合小数据集,计算量较大):

# 初始化Cook距离向量
cd <- numeric(nrow(data_select))
# 循环处理每个观测
for (i in 1:nrow(data_select)) {
  data_temp <- data_select[-i, ]
  # 尝试拟合删除当前观测后的模型,用原模型参数作为初始值加速拟合
  model_temp <- try(do.call(nlme,
                    list(formula,
                         fixed = c(p ~ 1, k ~ 1 + season2),
                         random = k ~ 1 | id,
                         data = data_temp,
                         start = list(fixed = fixef(model)),
                         na.action = na.exclude,
                         control=list(maxIter=1e6, msMaxIter = 1e6, msVerbose = FALSE)
                    )), silent = TRUE)
  # 若拟合成功则计算Cook距离,失败标记为NA
  if (!inherits(model_temp, "try-error")) {
    cd[i] <- t(fixef(model) - fixef(model_temp)) %*% solve(vcov(model)) %*% (fixef(model) - fixef(model_temp)) / p
  } else {
    cd[i] <- NA
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 18:02:47