ggplot2中为第二个geom_smooth设置颜色/线型并自定义图例
问题描述
我正在制作包含多组数据的图表,每组数据分别拟合两种线性模型:等权重模型、按分组区间内点数加权的模型。
模拟数据代码:
test_data <- bind_rows( tibble(test_x=rbeta(500,0.05,0.05), test_y=5*test_x+4+runif(length(test_x),0,3), group="group-a" ), tibble(test_x=rbeta(500,0.05,0.05), test_y=3*test_x+3+runif(length(test_x),0,3), group="group-b" ), ) |> mutate(test_x=floor(test_x * 20)/20 + 1/(2*20) ) |> group_by(test_x,group) |> summarise(n=n(),test_y=mean(test_y))
当前绘图代码:
test_data |> ggplot(aes(x=test_x,y=test_y,group=group,color=group)) + geom_point() +geom_smooth(method = lm,se=FALSE) + geom_smooth(aes(weight=n),method = lm,se=FALSE)
尝试给加权拟合线添加linetype="dashed"后,线型未显示在图例中。需求如下:
- 让线型信息显示在图例中
- 更理想的是,自定义图例,分别展示「group-a加权拟合」「group-a未加权拟合」「group-b加权拟合」「group-b未加权拟合」,每条线对应匹配的颜色/样式。
解决方案
方法1:分组与拟合类型联动,保留双图例
这种方式保留「分组」和「拟合类型」两个独立图例,颜色对应分组,线型对应加权/未加权状态:
library(ggplot2) library(dplyr) test_data |> ggplot(aes(x = test_x, y = test_y)) + # 原始数据点,按分组着色 geom_point(aes(color = group)) + # 未加权拟合线:实线,绑定分组颜色 geom_smooth( aes(group = paste(group, "unweighted"), color = group, linetype = "unweighted"), method = lm, se = FALSE ) + # 加权拟合线:虚线,绑定分组颜色,使用n作为权重 geom_smooth( aes(group = paste(group, "weighted"), color = group, linetype = "weighted", weight = n), method = lm, se = FALSE ) + # 自定义线型图例 scale_linetype_manual( name = "拟合类型", values = c("unweighted" = "solid", "weighted" = "dashed"), labels = c("未加权", "加权") ) + # 自定义分组颜色图例 scale_color_discrete(name = "分组") + labs(title = "分组加权/未加权线性拟合", x = "test_x", y = "test_y") + theme_minimal()
方法2:拆分所有拟合线为独立图例项
如果需要把每个组的两种拟合都作为单独的图例条目,可通过创建「分组+拟合类型」的组合变量实现:
# 预处理数据,复制并添加拟合类型标识 test_data_combined <- bind_rows( test_data |> mutate(model = "unweighted"), test_data |> mutate(model = "weighted") ) test_data_combined |> ggplot(aes(x = test_x, y = test_y)) + # 原始数据点,按分组着色 geom_point(aes(color = group)) + # 拟合线:按组合变量分组,颜色对应组合,线型对应拟合类型 geom_smooth( aes( group = interaction(group, model), color = interaction(group, model), linetype = model, weight = ifelse(model == "weighted", n, 1) ), method = lm, se = FALSE ) + # 自定义组合图例的标签 scale_color_discrete( name = "拟合组合", labels = c( "group-a.unweighted" = "group-a 未加权", "group-a.weighted" = "group-a 加权", "group-b.unweighted" = "group-b 未加权", "group-b.weighted" = "group-b 加权" ) ) + # 自定义线型图例 scale_linetype_manual( name = "拟合类型", values = c("unweighted" = "solid", "weighted" = "dashed"), labels = c("未加权", "加权") ) + labs(title = "分组加权/未加权线性拟合", x = "test_x", y = "test_y") + theme_minimal()
核心逻辑说明
- 让ggplot识别每条拟合线为独立分组:通过
paste(group, model)或interaction(group, model)生成唯一标识 - 权重绑定:加权模型使用
n作为权重,未加权模型使用默认等权重(或显式指定weight=1) - 图例自定义:通过
scale_*_manual或scale_color_discrete调整图例的名称、标签和样式,确保所有元素正确显示
内容的提问来源于stack exchange,提问作者HowYaDoing
相关产品推荐
相关产品推荐

