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

如何使用ggplot和ggfortify为第二幅图添加Cook's距离红色虚线等高线?

如何用ggplot2和ggfortify添加Cook's距离等高线到回归诊断图

没问题,我来帮你搞定这个Cook's距离等高线的添加!其实核心是先理清Cook's距离和学生化残差、杠杆值的数学关系,然后基于这个关系生成等高线数据,再把它叠加到ggfortify的诊断图上就行。

先搞懂Cook's距离的等高线公式

Cook's距离的计算公式是:

D_i = (r_i² / p) * (h_ii / (1 - h_ii)²)

其中:

  • r_i:第i个样本的学生化残差
  • h_ii:第i个样本的杠杆值(帽子矩阵的对角线元素)
  • p:模型的参数总数(包含截距项)
  • n:样本量

常用的Cook's距离临界值是 4/n(经验规则),我们要画的就是所有满足 D_i = 4/n 的点组成的曲线。把公式变形一下,就能得到学生化残差和杠杆值的关系:

r = ±√[ (4/n) * p * (1 - h)² / h ]

有了这个关系,我们就能生成等高线的坐标数据了。

具体代码实现(用mtcars数据集演示)

1. 准备模型和诊断数据

先拟合模型,提取我们需要的统计量:

library(ggplot2)
library(ggfortify)
library(dplyr)
library(broom)

# 拟合线性模型
model <- lm(mpg ~ wt + hp, data = mtcars)

# 提取诊断数据:学生化残差、杠杆值、参数数、样本量
diagnostics <- augment(model) %>%
  mutate(
    leverage = hatvalues(model),
    student_resid = rstudent(model),
    p = length(coef(model)),
    n = nrow(mtcars)
  )

2. 生成Cook's距离等高线数据

基于上面推导的公式,生成等高线的坐标点:

# 定义Cook's距离临界值
critical_D <- 4 / diagnostics$n[1]

# 生成杠杆值的序列(覆盖现有数据的杠杆值范围)
h_seq <- seq(min(diagnostics$leverage), max(diagnostics$leverage), length.out = 100)

# 计算对应学生化残差的上下边界
r_upper <- sqrt(critical_D * diagnostics$p[1] * (1 - h_seq)^2 / h_seq)
r_lower <- -r_upper

# 整理成ggplot可用的数据框
cook_contour_df <- data.frame(
  leverage = rep(h_seq, 2),
  student_resid = c(r_upper, r_lower)
)

3. 叠加等高线到ggfortify的诊断图

用autoplot生成残差-杠杆图,再用geom_path添加红色虚线等高线:

autoplot(model, which = 5, label.size = 3) +
  geom_path(
    data = cook_contour_df,
    aes(x = leverage, y = student_resid),
    color = "red",
    linetype = "dashed",
    linewidth = 1
  ) +
  labs(title = "学生化残差 vs 杠杆值(含Cook's距离等高线)")

另一种方法:用geom_contour直接绘制

如果你更习惯用geom_contour,可以先生成一个网格数据集,计算每个网格点的Cook's距离,再提取临界值对应的等高线:

# 生成覆盖残差和杠杆值范围的网格
grid_data <- expand.grid(
  leverage = seq(min(diagnostics$leverage), max(diagnostics$leverage), length.out = 100),
  student_resid = seq(min(diagnostics$student_resid), max(diagnostics$student_resid), length.out = 100)
) %>%
  mutate(
    # 计算每个网格点的Cook's距离
    cook_d = (student_resid^2 / diagnostics$p[1]) * (leverage / (1 - leverage)^2)
  )

# 绘制图并添加等高线
autoplot(model, which = 5, label.size = 3) +
  geom_contour(
    data = grid_data,
    aes(x = leverage, y = student_resid, z = cook_d),
    breaks = critical_D,
    color = "red",
    linetype = "dashed",
    linewidth = 1
  ) +
  labs(title = "学生化残差 vs 杠杆值(含Cook's距离等高线)")

注意事项

  • 临界值4/n是经验规则,你也可以根据需求换成其他值(比如1),只需要修改critical_D的赋值即可。
  • 确保你用的残差和杠杆值和ggfortify的图一致:autoplot(model, which=5)展示的是学生化残差和杠杆值,所以我们用rstudent(model)和hatvalues(model)是完全匹配的。
  • 如果你的模型没有截距项,记得调整p的计算(去掉截距的参数数)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 10:00:49