如何在R中绘制含双轴的两个GLM模型预测图(含数据点)
在R中绘制双轴预测图(整合两个GLM模型结果)
问题背景
你有如下示例数据和两个高斯族GLM模型,希望把两个模型的预测图(含原始数据点和拟合线)整合到一张双轴图中:左侧y轴对应RespVar1,右侧y轴对应RespVar2,x轴统一为PredVar。目前你用sjPlot的plot_model分别生成两张图,需要合并成单张双轴图。
示例数据代码:
RespVar1 <- runif(n=18, min=55, max=120) RespVar2 <- runif(n=18, min=0.3, max=0.5) PredVar <- c(-2, -1, 0, 1, 2, 3) df <- data.frame(RespVar1, RespVar2, PredVar)
模型拟合代码:
M1 <- glm(RespVar1 ~ PredVar, data=df, family=gaussian()) M2 <- glm(RespVar2 ~ PredVar, data=df, family=gaussian())
实现方案
用ggplot2结合sec_axis功能可以轻松实现,步骤如下:
1. 生成模型预测值及置信区间数据
先从两个模型中提取预测结果,和原始数据合并:
library(ggplot2) # 提取M1的预测值与标准误 pred_M1 <- predict(M1, newdata = df, se.fit = TRUE) df$pred1 <- pred_M1$fit df$se1 <- pred_M1$se.fit # 提取M2的预测值与标准误 pred_M2 <- predict(M2, newdata = df, se.fit = TRUE) df$pred2 <- pred_M2$fit df$se2 <- pred_M2$se.fit
2. 计算双轴刻度转换系数
因为两个响应变量的数值范围差异极大,需要把RespVar2的数值映射到RespVar1的轴范围,保证两个系列都能清晰展示:
# 计算缩放比例和偏移量 scale_factor <- diff(range(df$RespVar1)) / diff(range(df$RespVar2)) shift <- min(df$RespVar1) - min(df$RespVar2) * scale_factor
3. 绘制双轴图
把两个模型的点、线、置信区间都画到同一张图里,同时设置双轴:
ggplot(df, aes(x = PredVar)) + # 绘制M1的原始点、拟合线、置信区间 geom_point(aes(y = RespVar1), color = "#2196F3", size = 2) + geom_line(aes(y = pred1), color = "#2196F3", linewidth = 1) + geom_ribbon(aes(ymin = pred1 - 1.96*se1, ymax = pred1 + 1.96*se1), fill = "#2196F3", alpha = 0.2) + # 绘制M2的原始点、拟合线、置信区间(已转换到左侧轴刻度) geom_point(aes(y = RespVar2 * scale_factor + shift), color = "#F44336", size = 2) + geom_line(aes(y = pred2 * scale_factor + shift), color = "#F44336", linewidth = 1) + geom_ribbon(aes(ymin = (pred2 - 1.96*se2)*scale_factor + shift, ymax = (pred2 + 1.96*se2)*scale_factor + shift), fill = "#F44336", alpha = 0.2) + # 设置双轴:左侧为RespVar1,右侧为转换后的RespVar2 scale_y_continuous( name = "RespVar1", sec.axis = sec_axis(~ (. - shift)/scale_factor, name = "RespVar2") ) + labs(x = "PredVar") + theme_minimal() + theme(legend.position = "top")
补充说明
- 如果不需要置信区间,直接删除
geom_ribbon相关代码即可。 - 双轴图的核心是刻度转换的合理性,这里的转换是线性映射,保证两个变量的相对趋势不变。
内容的提问来源于stack exchange,提问作者Teresa
相关产品推荐
相关产品推荐

