如何将sjPlot的R模型结果导入ggplot2实现自定义并解决线条重叠?
解决sjPlot转ggplot2的线型叠加与简化实现问题
问题背景
使用R语言的nlme包拟合随机系数增长模型后,用sjPlot的plot_model快速生成预测可视化,但自定义能力有限。尝试将sjPlot生成的ggplot对象导入ggplot2进行样式调整时,出现线型叠加在实线上的问题,且现有实现方式繁琐,需要更优解决方案。
模拟数据与模型代码
模拟数据
dat <- data.frame( Event = c(1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4), Linear = c(0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3), Covariate1 = c(-1.0, -0.5, 0.0, 1.0, -0.5, 0.0, 1.0, 0.5, 0.5, 1.5, -2.0, 1.0, -2.0, -1.0, 1.0, 2.0), Covariate2 = c(1, 1, 0, 0, 0, 0, 1, 1, -1, -2, 1, 2, 2, 2, 1, 1), X1 = c(2, 1, 1, 0, 2, 1, 0, 2, 1, -2, -2, 0, 1, 2, -2, 0), X2 = c(-2, -2, -2, -2, 0, -1, 1, 0, -1, 1, -1, 1, 0, 0, -1, 1), X3 = c(2, -1, 1, 1, 1, 0, 2, -1, 2, -1, 2, -2, -1, 0, 1, -2), X4 = c(2, -2, -1, 1, -2, -2, -1, 2, 0, -1, 2, 0, 1, -2, 1, 1), Outcome = c(0.01, 0.20, 0.30, 0.40, -0.20, -0.20, -0.30, -0.40, -0.10, 0.00, 0.20, 0.30, 0.40, 0.60, 0.80, 0.90) )
拟合增长模型
library(nlme) mod <- lme(Outcome ~ 1 + Covariate1 + Covariate2 + Linear + I(Linear^2) + X1 + X2 + X3 + X4 + (Linear * X1) + (Linear * X2) + (Linear * X3) + (Linear * X4), random=~1|Event, correlation=corAR1(form=~1|Event), data=dat,method="ML", control=lmeControl(opt="optim"))
原sjPlot绘图代码
plot <- sjPlot::plot_model(mod,type="pred", terms=c("Linear [all]","X1"), axis.title=c("Time","Outcome"), title="Time by X1", ci.lvl=NA, legend.title="")
原自定义ggplot代码(存在问题)
plot + geom_line(aes(linetype = group, color = group), size = 1.5) + scale_color_manual(values = c("black", "grey", "brown"), labels = c("Low X1", "Average X1", "High X1")) + scale_linetype_manual(values = c("solid", "dashed", "dotted")) + guides(color = guide_legend(override.aes = list(linetype = c("solid", "dashed", "dotted"))), linetype = FALSE) + theme( legend.key = element_rect(fill = NA, color = NA) )
问题原因
原代码中,sjPlot的plot_model已经生成了默认的实线图层,之后调用geom_line相当于在原有实线上叠加了新的线型线条,导致视觉上出现"线型叠加在实线上"的效果,同时代码冗余。
优化解决方案
方案1:修改sjPlot生成的ggplot图层(轻量调整)
直接修改sjPlot生成的ggplot对象中已有的线条图层,避免重复绘制:
# 修改原有线条图层的映射与参数 plot$layers[[1]]$mapping <- aes(x = x, y = predicted, linetype = group, color = group) plot$layers[[1]]$size <- 1.5 # 添加自定义样式 plot + scale_color_manual(values = c("black", "grey", "brown"), labels = c("Low X1", "Average X1", "High X1")) + scale_linetype_manual(values = c("solid", "dashed", "dotted")) + guides(linetype = FALSE) + theme(legend.key = element_rect(fill = NA, color = NA))
方案2:提取预测数据,手动用ggplot绘制(推荐,完全可控)
直接提取模型预测数据,从头构建ggplot图表,彻底避免图层叠加问题,且自定义更灵活:
library(ggplot2) # 提取模型预测数据 pred_dat <- sjPlot::get_model_prediction(mod, type = "pred", terms = c("Linear [all]", "X1")) # 手动绘制ggplot ggplot(pred_dat$data, aes(x = x, y = predicted, linetype = group, color = group)) + geom_line(size = 1.5) + scale_color_manual(values = c("black", "grey", "brown"), labels = c("Low X1", "Average X1", "High X1")) + scale_linetype_manual(values = c("solid", "dashed", "dotted"), labels = c("Low X1", "Average X1", "High X1")) + labs(x = "Time", y = "Outcome", title = "Time by X1") + theme(legend.key = element_rect(fill = NA, color = NA))
说明
方案2更推荐,因为它完全脱离sjPlot的默认图层限制,所有样式都由你直接控制,代码逻辑更清晰,也不会出现图层叠加的问题。
内容的提问来源于stack exchange,提问作者a_roebuck
相关产品推荐
相关产品推荐

