ggplot绘制Gamma分布geom_smooth时反转Y轴报错解决方法
报错原因
scale_y_reverse()属于尺度层函数,执行顺序优先于统计计算:它会先将原始Y值取反,再传入stat_smooth()做Gamma广义线性模型拟合。而Gamma分布要求响应变量必须为严格正值,传入取反后的负值就会触发报错。
坐标层(coord_*系列)的调整发生在所有统计计算完成后,仅修改图形元素的最终显示位置,不会改动传入模型的原始数据,不会干扰拟合流程。
实现方案
方案1:坐标层反转(推荐)
无需提前手动拟合,直接通过coord_cartesian()设置反向Y轴范围即可,geom_smooth()自带的拟合线、置信区间都能正常渲染:
# 注意:原代码包名存在笔误,ggplot2才是正确的包名 library(ggplot2) set.seed(123) # 固定随机种子方便复现 data <- data.frame(x = 1:100, y = (1:100 + runif(100, min = 0, max = 50))^2) p <- ggplot(data, aes(x, y)) + geom_point() + geom_smooth(method = 'glm', method.args = list(family = Gamma(link = "log"))) # Y轴范围按「最大值到最小值」设置,即可实现Y轴反转显示 p + coord_cartesian(ylim = rev(range(data$y)))
如果需要自定义Y轴显示范围,直接传入反向的边界值即可,例如要将Y轴范围限定在0到25000,反转后参数写为ylim = c(25000, 0)。
方案2:提前拟合后反转尺度
如果需要搭配尺度层的其他自定义配置,可以先手动完成模型拟合、计算好拟合值和置信区间,再调用scale_y_reverse(),此时统计计算已经完成,不会触发报错:
library(ggplot2) set.seed(123) data <- data.frame(x = 1:100, y = (1:100 + runif(100, min = 0, max = 50))^2) # 拟合Gamma GLM模型 gamma_fit <- glm(y ~ x, family = Gamma(link = "log"), data = data) # 计算拟合值和95%置信区间 pred <- predict(gamma_fit, newdata = data.frame(x = 1:100), type = "response", se.fit = TRUE) data$fit <- pred$fit data$ci_upper <- pred$fit + 1.96 * pred$se.fit data$ci_lower <- pred$fit - 1.96 * pred$se.fit # 手动绘制散点、置信带、拟合线后反转Y轴 ggplot(data, aes(x, y)) + geom_point() + geom_ribbon(aes(ymin = ci_lower, ymax = ci_upper), alpha = 0.2, fill = "#3366FF") + geom_line(aes(y = fit), color = "#3366FF", linewidth = 1) + scale_y_reverse()
两种方案最终展示效果一致,优先选方案1,代码更简洁,不需要手动处理置信区间计算逻辑。
内容的提问来源于stack exchange,提问作者Muon
相关产品推荐
相关产品推荐

