如何解决ggplot分面geom重复绘制导致的透明度异常
如何防止ggplot在每个分面中重复绘制各类geom几何对象?
问题描述
- 绘制多面板分面图时,x轴对应温度(摄氏度)维度,计划添加两个
geom_rect()图层,分别标记温度低于冰点、高于冰点的区间。 - 实际渲染出现异常:分组"A"中
geom_rect仅绘制1次,分组"B"中geom_rect绘制2次,分组"C"中geom_rect绘制3次。 - 异常带来的表现差异:由于不同分面中
geom_rect的重复绘制次数不一致,各分面的alpha透明度表现不统一,可观察到从上到下透明度逐渐加深的问题。
问题复现代码
library(tidyverse) set.seed(1) df <- tibble( facet_var = c("A", "B", "B", "C", "C", "C"), celcius = rnorm(n = 6), y = as.factor(c(1, 1, 2, 1, 2, 3))) df %>% ggplot(aes(x = celcius, y = y))+ geom_point()+ geom_rect(xmin = -2.5, xmax=0.0, ymax=3.5 , ymin=0, fill = "blue", alpha =0.2)+ geom_rect(xmin = 0, xmax=2, ymax=3.5, ymin=0, fill = "red", alpha =0.2)+ facet_grid(rows = vars(facet_var), scales = "free_y", space = "free_y")

示例由reprex包(v2.0.1)于2022-06-30创建生成
问题原因
ggplot默认会继承全局数据集的映射规则,全局添加的geom_rect会按照主数据集的每一行对应绘制一次:A组对应1行数据就绘制1次矩形,B组对应2行数据就绘制2次矩形,C组对应3行数据就绘制3次矩形。多次绘制的半透明矩形叠加后,就会出现分面间透明度不一致的问题。
解决方案
方法1:给注释类图层传入独立数据集
给geom_rect单独传入仅包含分面变量唯一值的独立数据集,同时设置inherit.aes = FALSE关闭全局映射继承,即可保证每个分面仅绘制1次矩形,透明度完全统一。
# 构造矩形图层专用数据集,每个分面对应1行记录 rect_data <- tibble(facet_var = c("A", "B", "C")) df %>% ggplot(aes(x = celcius, y = y))+ geom_point()+ geom_rect(data = rect_data, xmin = -2.5, xmax=0.0, ymax=3.5 , ymin=0, fill = "blue", alpha =0.2, inherit.aes = FALSE)+ geom_rect(data = rect_data, xmin = 0, xmax=2, ymax=3.5, ymin=0, fill = "red", alpha =0.2, inherit.aes = FALSE)+ facet_grid(rows = vars(facet_var), scales = "free_y", space = "free_y")
该方法适配分面坐标轴自由缩放的场景,矩形范围会跟随各分面的坐标轴范围自动适配。
方法2:使用annotate()函数添加注释
如果不需要注释图层跟随分面坐标轴调整范围,可以直接用annotate()函数添加矩形,该函数生成的图层默认仅全局绘制1次,不会按数据行重复生成,写法更简洁:
df %>% ggplot(aes(x = celcius, y = y))+ geom_point()+ annotate(geom = "rect", xmin = -2.5, xmax=0.0, ymax=3.5 , ymin=0, fill = "blue", alpha =0.2)+ annotate(geom = "rect", xmin = 0, xmax=2, ymax=3.5, ymin=0, fill = "red", alpha =0.2)+ facet_grid(rows = vars(facet_var), scales = "free_y", space = "free_y")
内容的提问来源于stack exchange,提问作者Steen Harsted
相关产品推荐
相关产品推荐

