如何在R的ggplot2中结合facet_grid自定义各面板Y轴
解决facet_grid面板Y轴从0开始并自定义最大值的问题
先优化你的原代码(清理冗余)
原代码存在重复的坐标轴标签调用,且两次geom_point可按需调整,优化后代码:
ggplot(data = graph2_old_longer, aes(x = Distance, y = concentration, col = factor(Year))) + geom_point() + geom_point(shape = 1) + # 叠加空心点,不需要可删除 scale_color_discrete(name = "") + labs(y = "Concentration (mg/L)", x = "Distance (m)") + facet_grid(vars(analyte), scales = "free")
核心需求实现:Y轴从0开始+自定义每个面板最大值
ggplot2 3.3.0及以上版本支持facetted_pos_scales()函数,可单独为每个分面板设置坐标轴范围,这是最直接的解决方案:
方法1:手动指定每个analyte的Y最大值
假设你的三个analyte分别为A、B、C,对应Y轴最大值设为10、20、15,代码如下:
library(ggplot2) ggplot(data = graph2_old_longer, aes(x = Distance, y = concentration, col = factor(Year))) + geom_point() + geom_point(shape = 1) + scale_color_discrete(name = "") + labs(y = "Concentration (mg/L)", x = "Distance (m)") + facet_grid(vars(analyte), scales = "free") + # 为每个面板设置Y轴范围:起始值固定为0,上限自定义 facetted_pos_scales( y = list( analyte == "A" ~ scale_y_continuous(limits = c(0, 10)), analyte == "B" ~ scale_y_continuous(limits = c(0, 20)), analyte == "C" ~ scale_y_continuous(limits = c(0, 15)) ) )
方法2:基于数据自动计算每个analyte的Y最大值
如果不想手动输入最大值,可基于每个analyte的实际最大浓度自动调整(比如取最大值的1.1倍留余量),先预处理数据再绘图:
library(ggplot2) library(dplyr) # 计算每个analyte的最大浓度,乘以1.1作为Y轴上限 y_limits <- graph2_old_longer %>% group_by(analyte) %>% summarise(max_y = max(concentration, na.rm = TRUE) * 1.1) # 绘图时调用facetted_pos_scales设置每个面板的Y轴范围 ggplot(data = graph2_old_longer, aes(x = Distance, y = concentration, col = factor(Year))) + geom_point() + geom_point(shape = 1) + scale_color_discrete(name = "") + labs(y = "Concentration (mg/L)", x = "Distance (m)") + facet_grid(vars(analyte), scales = "free") + facetted_pos_scales( y = purrr::map2(y_limits$analyte, y_limits$max_y, function(an, my) { analyte == an ~ scale_y_continuous(limits = c(0, my)) }) )
注意事项
- 确保ggplot2版本≥3.3.0,版本过低可通过
install.packages("ggplot2")升级 - 若不想使用
facetted_pos_scales,可临时用coord_cartesian(ylim = c(0, NA))强制Y轴从0开始,但无法单独自定义每个面板的最大值,因此优先推荐前者 - 原代码中两次
geom_point若要实现「彩色实心点+黑色空心点」效果,建议修改第二次调用:geom_point(shape = 1, color = "black", inherit.aes = FALSE),避免继承颜色映射
内容的提问来源于stack exchange,提问作者Haley McLean
相关产品推荐
相关产品推荐

