如何为基于ggplot2的分面网格图表手动添加自定义分组图例
如何为基于ggplot2的分面网格图表手动添加自定义分组图例
我来帮你搞定这个需求!你已经成功给不同品牌的分面背景设置了对应颜色,现在要加一个能说明“橙色=欧洲、蓝色=日本”的图例,核心思路是先给数据绑定「品牌-地区」的分组关系,再通过一个隐藏图层让ggplot自动生成我们需要的图例,最后调整图例的样式和位置就行。下面是完整的修改后的代码和步骤说明:
第一步:给数据添加地区分组
首先在处理原始数据时,新增一列region来标记每个品牌所属的地区,这样我们有明确的“地区-颜色”映射基础:
library(tidyverse) library(ggh4x) dat <- mtcars |> mutate(vehicle = rownames(mtcars)) |> separate(col = vehicle, into = c('make', 'trash'), sep = ' ') |> filter(make %in% c('Merc', 'Fiat', 'Toyota')) |> select(make, mpg, cyl) |> relocate(make) |> # 新增地区分组:Merc和Fiat属于欧洲,Toyota属于日本 mutate(region = case_when( make %in% c('Merc', 'Fiat') ~ 'Europe', make == 'Toyota' ~ 'Japan', TRUE ~ NA_character_ ))
第二步:建立地区与颜色的映射
把原来的品牌-颜色映射,改成更灵活的地区-颜色映射,再基于这个生成品牌的颜色(保证分面背景色和图例颜色完全一致):
# 地区到颜色的核心映射(后续图例和分面都用这个) region_cols <- c(Europe = "orange", Japan = "dodgerblue") # 基于地区映射生成品牌的颜色向量,和你原来的make_cols效果完全一致 make_cols <- dat |> distinct(make, region) |> pull(region, name = make) |> recode(!!!region_cols)
第三步:绘图并添加自定义图例
这里关键是用geom_blank()添加一个隐藏图层,让ggplot识别「地区-颜色」的映射关系,从而生成对应的图例,再调整图例的样式(比如改成方块、放在图的上方):
dat |> pivot_longer(cols = 2:3, names_to = 'variable', values_to = 'value') |> ggplot(aes(x = make, y = value)) + # 绘制原始散点 geom_point() + # 隐藏图层:仅用于触发图例生成,不会在图上显示任何额外元素 geom_blank(aes(color = region)) + labs(x = NULL, y = NULL) + theme_bw(base_size = 18) + theme( strip.background.y = element_rect(fill = 'white'), axis.text.x = element_blank(), # 把图例放到图的顶部,水平排列 legend.position = "top", legend.direction = "horizontal", # 去掉图例的标题,让布局更简洁 legend.title = element_blank(), # 调整图例元素的间距,提升美观度 legend.spacing.x = unit(1, 'cm') ) + # 指定地区的颜色映射,同时把图例符号改成实心方块(和分面背景的矩形匹配) scale_color_manual( values = region_cols, guide = guide_legend( override.aes = list(shape = 15, size = 8) # shape=15是实心方块,size调大更显眼 ) ) + ggh4x::facet_grid2( rows = vars(variable), cols = vars(make), strip = ggh4x::strip_themed( background_x = ggh4x::elem_list_rect(fill = make_cols) ) )
效果说明
这样生成的图会在顶部显示一个水平排列的图例:橙色方块对应“Europe”,蓝色方块对应“Japan”,和你设置的分面背景色完全对应。geom_blank()不会干扰原始图表的内容,只是帮我们触发图例的生成;override.aes把默认的圆形图例符号改成了实心方块,和分面的背景形状呼应,更直观。
如果想让图例方块和分面背景的风格更统一,还可以在override.aes里加上color = "black",给方块添上黑色边框,和theme_bw的主题风格匹配。
内容来源于stack exchange
相关产品推荐
相关产品推荐

