如何在ggplot2中为不同分面单独控制并扩大Y轴范围
问题描述
用ggpubr绘制带组间t检验p值标签的分面散点图时,顶部的p值标签总是显示不全。试了用ylim(0, max(data$values)+5)扩展Y轴,但R用的是全局最大值,不是每个分面自己的子集最大值,结果根本不符合预期。想解决:
- 怎么给不同分面单独调Y轴范围?
- 为啥分面不会自动用对应子集的最大值来适配标签?
- 怎么给分面传对应子集的数值来调整轴范围?
示例代码:
library(ggplot2) library(ggpubr) set.seed(42) data <- data.frame(category = c("green", "red", "blue", "yellow"), type = sample(LETTERS[1:4], 100, replace = T), values = c(1, 2, 50, 5) * runif(100)) ggplot(data, aes(x = type, y = values, color = type)) + geom_point(size = 3) + stat_compare_means(method = "t.test", aes(label = ..p.value..), size = 5, comparisons = list(c("A" , "C"), c("A" , "D"))) + facet_wrap( ~ category, scales = "free_y")
解决方案
1. 给每个分面单独设Y轴范围
方法一:用ggh4x包(最方便)
ggh4x的facetted_pos_scales能给每个分面单独设置轴范围,步骤如下:
library(ggh4x) library(dplyr) # 先算每个category的values最大值,再加个偏移量(比如最大值的15%,根据标签大小调整) y_limits <- data %>% group_by(category) %>% summarise(ymax = max(values) + max(values)*0.15) # 把每个分面的Y轴设置做成列表 scale_list <- set_names(map(y_limits$ymax, ~ scale_y_continuous(limits = c(0, .x))), y_limits$category) # 绘图时调用这个列表 ggplot(data, aes(x = type, y = values, color = type)) + geom_point(size = 3) + stat_compare_means(method = "t.test", aes(label = ..p.value..), size = 5, comparisons = list(c("A" , "C"), c("A" , "D"))) + facet_wrap( ~ category, scales = "free_y") + facetted_pos_scales(y = scale_list)
方法二:微调标签位置(应急用)
如果不想装新包,可以试试调整标签的垂直位置,但如果标签太大还是会溢出,不如扩轴靠谱:
stat_compare_means(method = "t.test", aes(label = ..p.value..), size = 5, comparisons = list(c("A" , "C"), c("A" , "D")), vjust = -0.5) # 把标签往上挪一点
2. 为啥分面不会自动适配标签?
ggplot2的facet_wrap(scales = "free_y")只会根据你原始数据里的values列范围设置Y轴,而stat_compare_means生成的标签是绘图时额外计算出来的,不在原始数据的数值范围内,所以默认不会被纳入轴范围的计算逻辑里。
3. 给分面传子集数值的方法
用dplyr分组计算每个分面的关键数值就行,比如:
library(dplyr) data_adjusted <- data %>% group_by(category) %>% mutate(group_max = max(values), y_upper = group_max + group_max*0.15) %>% # 算出每个分面需要的Y轴上限 ungroup()
算出的y_upper就能用来给每个分面设置Y轴范围,就像方法一里的y_limits数据框那样使用。
内容的提问来源于stack exchange,提问作者Eugene
相关产品推荐
相关产品推荐

