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

如何将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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 12:39:49