如何在ggplot2边距中实现位置固定的刻度标签,无需hack调整?
ggplot2边距固定位置刻度极点标签实现方案
需求说明
需要在ggplot2的边距区域添加固定位置的刻度极点标签,同类图表切换时标签不会发生位移。原实现方案需要根据X轴分类水平数动态计算标签位置,属于临时hack,存在适配性差的问题。
可行实现方案
无需依赖数据坐标计算位置,直接使用grid包的归一化父坐标(NPC)即可实现,坐标取值范围为0-1,相对于绘图面板的边界定位,完全不受数据维度影响。
改进后代码
library(ggplot2) library(grid) library(tidyverse) dat = data.frame("Country" = c(rep("USA",50), rep("Canada",50), rep("Japan",50), rep("Poland",50), rep("Germany",50)), "Outcome" = c(rnorm(n = 50, mean = 4.0, sd = 1.0), rnorm(n = 50, mean = 5.0, sd = 0.5), rnorm(n = 50, mean = 3.0, sd = 1.5), rnorm(n = 50, mean = 4.5, sd = 1.0), rnorm(n = 50, mean = 4.5, sd = 1.5)) ) myfunction = function(data, IV, DV, varlevels){ # 计算均值用于绘图 as_tibble(data) %>% group_by({{IV}}) %>% summarise(Outcome = mean({{DV}},na.rm=T)) %>% ggplot(mapping = aes({{IV}}, Outcome, fill = {{IV}})) + geom_col() + scale_x_discrete(limits = {{varlevels}}) + scale_y_continuous(breaks = c(1:7), limits = c(1,7), oob = scales::squish) + theme(legend.position = "none", # 调整左边距避免标签被裁切 plot.margin = unit(c(0.5,0.5,0.5,1), "lines")) + coord_cartesian(clip = "off") + # 用NPC坐标定位,x=-0.1代表绘图面板左边界往左10%的位置,固定不变 annotation_custom( grob = textGrob(label = "Good", gp = gpar(col = "grey50"), rot = 90, x = unit(-0.1, "npc"), y = unit(6.5, "native")), xmin = -Inf, xmax = Inf, ymin = -Inf, ymax = Inf ) + annotation_custom( grob = textGrob(label = "Bad", gp = gpar(col = "grey50"), rot = 90, x = unit(-0.1, "npc"), y = unit(1.5, "native")), xmin = -Inf, xmax = Inf, ymin = -Inf, ymax = Inf ) } # 测试不同分类数的图表,标签位置保持一致 myfunction(data = dat, IV = Country, DV = Outcome, varlevels = c("USA","Canada","Japan","Poland","Germany")) ggsave("outcome_by_country.png", dpi = 300, units = "in", height= 5.89, width = 6.69)
方案说明
- 标签的X坐标使用
unit(-0.1, "npc")定义,相对于绘图面板的左边界定位,无论X轴有多少个分类,该位置都固定不变 - Y坐标使用
unit(1.5, "native")保持和原方案一致的Y轴数据坐标定位,符合刻度标签和Y轴刻度对应的需求 - 仅需调整
plot.margin的左边距参数避免标签被裁切,无需其他额外适配
内容的提问来源于stack exchange,提问作者sachem87
相关产品推荐
相关产品推荐

