如何让ggplot2图例为同一colour美学的不同类别显示对应专属geom
问题:自定义ggplot2图例,按数据源匹配对应几何图形
我用point、pointrange和line三种geom绘制不同类型数据,通过颜色区分数据源。现在图例同时显示所有geom的样式,需要调整成:
- "acs 1-year"仅显示pointrange样式
- "admin v1"和"admin v2"仅显示line样式
- "decennial census"仅显示point样式
同时要保留基于colour美学的单个统一图例。
复现数据
df <- structure(list(year = c(1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022), admin1 = c(105939L, 105568L, 105207L, 105252L, 104878L, 104498L, 103960L, 104071L, 103689L, 103474L, 104039L, 104874L, 104949L, 105767L, 106559L, 107339L, 106348L, 105580L, 104455L, 102815L, 101121L, 99244L, 96823L, 95091L, 94082L, 92769L, 91811L, 91680L, 91350L, 82767L, 89030L, 89764L, 89942L ), admin2 = c(105944L, 105573L, 105209L, 105254L, 104880L, 104500L, 103961L, 104072L, 103691L, 103475L, 104039L, 104874L, 104949L, 105767L, 106559L, 107339L, 106348L, 106021L, 104874L, 103208L, 101580L, 99732L, 97343L, 95648L, 94685L, 93390L, 92467L, 92375L, 92137L, 92703L, 93417L, 94222L, 95200L), decennial_count = c(107682, NA, NA, NA, NA, NA, NA, NA, NA, NA, 105235, NA, NA, NA, NA, NA, NA, NA, NA, NA, 100296, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), acs1 = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 113122, 109275, 105005, 105918, 104330, 102660, 98506, 95432, 97196, 97841, 94046, 93184, 92218, 96609, 92982, NA, 96044, NA), acs1_moe = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 4433, 3735, 3484, 3227, 3379, 3527, 3171, 3259, 3105, 3800, 3711, 3232, 3507, 3816, 3261, NA, 3817, NA)), row.names = c(NA, -33L), class = c("tbl_df", "tbl", "data.frame" ))
原绘图代码
ggplot(df) + geom_line(aes(x = year, y = admin1, color = "admin v1")) + geom_line(aes(x = year, y = admin2, color = "admin v2")) + geom_pointrange(aes(x = year, y = acs1, ymin = (acs1 - acs1_moe), ymax = (acs1 + acs1_moe), color = "acs 1-year")) + geom_point(aes(year, decennial_count, color = "decennial census"), size = 4, shape = "diamond")
解决方法
核心思路是通过guides()的override.aes参数,针对每个图例项单独设置显示的几何元素,隐藏不需要的样式,同时保留统一的颜色图例。
修改后代码
library(ggplot2) ggplot(df) + geom_line(aes(x = year, y = admin1, color = "admin v1")) + geom_line(aes(x = year, y = admin2, color = "admin v2")) + geom_pointrange(aes(x = year, y = acs1, ymin = (acs1 - acs1_moe), ymax = (acs1 + acs1_moe), color = "acs 1-year")) + geom_point(aes(year, decennial_count, color = "decennial census"), size = 4, shape = "diamond") + guides(color = guide_legend( override.aes = list( # 按图例顺序设置:admin v1, admin v2, decennial census, acs 1-year shape = c(NA, NA, 18, NA), # 仅decennial census显示菱形点,其余隐藏 linetype = c(1, 1, 0, 1), # 仅decennial census隐藏线,其余显示实线 size = c(0.5, 0.5, 4, 0.5), # 匹配原图的点/线大小 ymin = c(NA, NA, NA, mean(df$acs1, na.rm = TRUE)), # 仅acs 1-year显示误差线下限 ymax = c(NA, NA, NA, mean(df$acs1, na.rm = TRUE)) # 仅acs 1-year显示误差线上限 ) )) + # 固定图例顺序,避免自动排序混乱 scale_color_discrete(breaks = c("admin v1", "admin v2", "decennial census", "acs 1-year"))
关键说明
override.aes内的参数顺序必须和图例项的顺序完全对应(可通过scale_color_discrete(breaks)手动指定顺序)- 用
NA隐藏不需要显示的几何元素:比如给不需要点的类别设shape=NA,不需要线的类别设linetype=0 - 误差线的
ymin和ymax仅给acs 1-year设置有效值,其余设为NA,确保只有它显示误差线
内容的提问来源于stack exchange,提问作者John J.
相关产品推荐
相关产品推荐

