使用scale_color_manual控制多数据组图例的点线样式与颜色
解决ggplot2 facet_wrap中图例显示异常问题
问题描述
此前在facet_wrap中为同一子集添加多条回归线时,遇到图例显示异常:需要Source组仅显示指定色盲友好配色的点(无连线),Fit组仅显示黑色回归线(无点),但现有代码运行后出现两种问题:
- 未设置
stat_smooth的color时,Fit组图例呈现彩色连线; - 设置
stat_smooth的color="black"后,Source组图例出现黑色连线,且Fit组图例有点状标记。
原始代码
output_df <- data.frame(year=c(1993,1993,1995,1995,1998,1998,2001,2001, 1993,1993,1995,1995,1998,1998,2001,2001), treatment_scen=c("CR","CR","CR","CR","CR","CR","CR","CR", "NT","NT","NT","NT","NT","NT","NT","NT"), val=c(7.16875,22.60000,23.03250,24.30000, 29.46125,23.60000,21.41375,24.80000, 9.11125,25.30000,27.13950,26.60000, 30.46950,24.90000,24.60500,26.10000), Source=c("Observed","Model","Observed","Model", "Observed","Model","Observed","Model", "Observed","Model","Observed","Model", "Observed","Model","Observed","Model") ) trendlines_df <- data.frame(year=c(1993,1993,1995,1995, 1998,1998,2001,2001, 1993,1993,1995,1995, 1998,1998,2001,2001), treatment_scen=c("CR","CR","CR","CR", "CR","CR","CR","CR", "NT","NT","NT","NT", "NT","NT","NT","NT"), Fit=c("AllObs","OutlierRemoved","AllObs","OutlierRemoved", "AllObs","OutlierRemoved","AllObs","OutlierRemoved", "AllObs","OutlierRemoved","AllObs","OutlierRemoved", "AllObs","OutlierRemoved","AllObs","OutlierRemoved"), value=c(7.16875,NA,23.03250,23.03250, 29.46125,29.46125,21.41375,21.41375, 9.11125,NA,27.13950,27.13950, 30.46950,30.46950,24.60500,24.60500), Source=c("Observed","Observed","Observed","Observed", "Observed","Observed","Observed","Observed", "Observed","Observed","Observed","Observed", "Observed","Observed","Observed","Observed"), Model=c("Observed","Observed","Observed","Observed", "Observed","Observed","Observed","Observed", "Observed","Observed","Observed","Observed", "Observed","Observed","Observed","Observed") ) # 9-color palette with grey and black. Colors in order are: #[1]black, [2]dark blue, [3]green, [4]light blue, [5]grey, #[6]pink, [7]red, [8]orange, [9]yellow cbPalette9 <- c("#000000","#0072B2","#009E73","#56B4E9","#999999", "#CC79A7","#D55E00","#E69F00","#F0E442") g1 <- output_df %>% ggplot(aes(x=year, y=val, color=Source, show.legend=TRUE)) + geom_point(show.legend=TRUE) + xlab("Year") + stat_smooth( data = trendlines_df, aes(linetype = Fit, y=value), #color="black", method = lm, se = FALSE, show.legend = TRUE, fullrange=TRUE ) + scale_color_manual(labels=c("Model","Observed"), values=cbPalette9[c(8,3)]) + facet_wrap(~treatment_scen,nrow=1) g1
异常效果
未设置黑色线条时的输出:

设置黑色线条后的输出:

解决方案
核心思路是分离点和线条的美学映射,并通过guides()定制图例显示:
- 将
color=Source的映射从全局aes移到geom_point中,避免stat_smooth继承颜色映射; - 固定
stat_smooth的线条颜色为黑色; - 分别对两个图例进行外观覆盖,确保Source图例仅显示点,Fit图例仅显示黑色线条。
修改后的代码:
g1 <- output_df %>% ggplot(aes(x=year, y=val)) + # 全局aes仅保留x、y,去掉color映射 geom_point(aes(color=Source), show.legend=TRUE) + # 点单独绑定color=Source xlab("Year") + stat_smooth( data = trendlines_df, aes(linetype = Fit, y=value), color="black", # 固定回归线为黑色 method = lm, se = FALSE, show.legend = TRUE, fullrange=TRUE ) + scale_color_manual(labels=c("Model","Observed"), values=cbPalette9[c(8,3)]) + facet_wrap(~treatment_scen,nrow=1) + guides( # 定制Source图例:仅显示点,移除连线 color = guide_legend(override.aesthetics = list(linetype = "blank")), # 定制Fit图例:仅显示黑色线条,移除点标记 linetype = guide_legend(override.aesthetics = list(color = "black", shape = NA)) ) g1
效果说明
修改后:
Source图例仅显示指定配色的点状标记,无多余连线;Fit图例仅显示黑色的不同线型,无点状标记;- 图中回归线保持黑色,点的颜色符合色盲友好配色要求。
内容的提问来源于stack exchange,提问作者E Maas
相关产品推荐
相关产品推荐

