ggplot2/ggh4x多图例互相干扰,多余fill图例如何优雅解决
问题根因
多余图例来自第一个柱状图层的fill = target映射:你虽然用ggh4x::scale_listed的自定义美学接管了展示逻辑,但原生fill美学的映射仍然存在,ggplot会自动为它生成默认图例。
规范解决方案
不需要额外的隐藏逻辑,只要调整映射关系,让自定义美学完全接管对应样式的渲染即可,修改后的代码如下:
library(ggplot2) library(ggh4x) my_data1 <- data.frame(case = "UK", target = rep(c("IN", "OUT"), 5), values = 1:10, step = as.character(rep(1:2, 5)), label = rep(c("A", "B"), 5)) p <- ggplot() + geom_bar(data = my_data1, position = position_stack(reverse = TRUE), # 去掉原生fill映射,只保留自定义美学映射 mapping = aes(x = step, y = values, my_target_scale = target), stat = "identity", na.rm = TRUE) + geom_bar(data = data.frame(step = 1:2, purpose = "TOTAL", values = c(20, 40)), inherit.aes = FALSE, # 保留color映射关联自定义美学 mapping = aes(x = step, y = values, color = purpose, my_total_scale = purpose), show.legend = TRUE, position = "stack", stat = "identity", fill = NA, na.rm = TRUE) + ggh4x::scale_listed(scalelist = list( scale_fill_manual(aesthetics = "my_target_scale", name = "GROUP:", values = c("IN" = "red", "OUT" = "green"), breaks = c("IN", "OUT"), labels = c("Incoming", "Outgoing") ), scale_color_manual(aesthetics = "my_total_scale", name = "Label:", values = c("TOTAL" = "black"), breaks = c("TOTAL"), labels = c("EVErYTHING") ) ), # 自定义美学分别对应替换原生fill、color的渲染逻辑 replaces = c("fill", "color") ) + theme_bw() + theme(panel.spacing = unit(.01, "lines"), legend.position = "bottom", legend.box = "horizontal") p
修改点说明
- 移除了第一个
geom_bar里aes中的fill = target映射,直接让自定义的my_target_scale接管填充样式的渲染,不会再触发生成原生fill图例 - 补全了第二个
geom_bar里aes中的color = purpose映射,和自定义的my_total_scale对应,边框颜色统一在scale中定义,逻辑更清晰 - 完全不需要额外的隐藏图例的hack代码,自定义图例的结构和样式完全保留,适配复杂图表的扩展需求
内容的提问来源于stack exchange,提问作者mnist
相关产品推荐
相关产品推荐

