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

使用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()定制图例显示:

  1. 将color=Source的映射从全局aes移到geom_point中,避免stat_smooth继承颜色映射;
  2. 固定stat_smooth的线条颜色为黑色;
  3. 分别对两个图例进行外观覆盖,确保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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 11:05:00