ggplot2:y轴标签在绘图区域内左对齐 [英] ggplot2: y axis labels left-justified inside plot area
问题描述
我正在寻找一种自动移动y轴刻度标签的方法,以使它们在实际绘图区域内显示为左对齐的.我喜欢ggplot中主题组件的通用灵活性,但是遇到了麻烦,试图找到一种通用的方式来实现此目的.
I'm looking for a way to automatically move the y-axis tick labels so that they appear left-justified within the actual plot area. I love the general flexibility of theme components in ggplot, but ran into a wall trying to find a general way to do this.
我知道给 axis.text.y
和 just = 0
并加上负的右边距(* gag *)可以达到这种效果,但是负的空白必须手动设置以匹配最长的y轴刻度标签的宽度.
I know giving axis.text.y
a combination of hjust=0
and a negative right margin (*gag*) can accomplish this effect, but the negative margin has to be manually set to match the width of the longest y-axis tick label.
作为示例,请考虑以下代码:
As an example, consider the following code:
library(ggplot2)
set.seed(0)
dat <- data.frame(x = 1:100, y = (1:100) + runif(100, -10, 10))
p1 <- ggplot(dat, aes(x, y)) +
geom_line() +
scale_y_continuous("", breaks = c(0, 30, 60, 90),
labels = c(0, 30, 60, "90 units of something")) +
theme(axis.text.y = element_text(hjust = 0,
margin = margin(0, -3.1, 0, 0, 'cm')))
我认为它很好地将y轴标签(例如某物的单位"
)合并到绘图主体中,但是为了实现它,请使用 -3.1
的最后一行必须手动找到(通过反复试验),这增加了侮辱性伤害:我不仅使用负边距将文本拖到不需要的位置,而且还抛出了带有一些神秘的,易碎的,硬编码的魔术数字.
I think it elegantly incorporates the y-axis label (e.g., "units of something"
) into the body of the plot, but in order to accomplish it, the -3.1
in the last line has to be found manually (by trial and error), which adds insult to injury: not only am I using a negative margin to pull text where it doesn't want to be -- I'm throwing in some arcane, fragile, hard-coded magic number.
有人知道我可以在哪里找到更通用,更优雅的解决方案吗?
Does anyone know where I can look for a more general and elegant solution to this problem?
推荐答案
这是一个使用grobs的骇客,它将y轴标签从其原始位置移开,以覆盖绘图区域.
Here's a hack using grobs, which shifts the y-axis labels away from its original position to overlap the plot area.
虽然我认为它不是很优雅(毕竟这是一种需要在 ggplotGrob
中进行转换的hack),但定位不是硬编码的,&您可以在转换之前 ggplot()
中指定所需的主题控件.
While I don't consider it exactly elegant (it's a hack that requires conversion in ggplotGrob
after all), the positioning is not hard-coded, & you can specify whatever theme control you want in ggplot()
before conversion.
设置:
library(ggplot2)
library(grid)
library(gtable)
# sample data
set.seed(0)
dat <- data.frame(x=1:100, y=(1:100) + runif(100, -10, 10))
# create ggplot object
p <- ggplot(dat, aes(x, y)) +
geom_line() +
scale_y_continuous("",
breaks = c(0, 30, 60, 90),
labels = c(0, 30, 60, "90 units of something")) +
# left-align y-axis labels
# you can also specify other theme parameters as desired
theme(axis.text.y = element_text(hjust = 0))
不知所措:
# convert from ggplot to grob object
gp <- ggplotGrob(p)
# locate the grob that corresponds to y-axis labels
y.label.grob <- gp$grobs[[which(gp$layout$name == "axis-l")]]$children$axis
# remove y-axis labels from the plot, & shrink the space occupied by them
gp$grobs[[which(gp$layout$name == "axis-l")]] <- zeroGrob()
gp$widths[gp$layout$l[which(gp$layout$name == "axis-l")]] <- unit(0, "cm")
使用水平顺序[ticks] [labels] [buffer space]为y轴刻度/标签定义一个新的grob:
Define a new grob for the y-axis ticks / labels, with the horizontal order [ticks][labels][buffer space]:
# create new gtable
new.y.label.grob <- gtable(heights = unit(1, "npc"))
# place axis ticks in the first column
new.y.label.grob <- gtable_add_cols(new.y.label.grob,
widths = y.label.grob[["widths"]][2])
new.y.label.grob <- gtable_add_grob(new.y.label.grob,
y.label.grob[["grobs"]][[2]],
t = 1, l = 1)
# place axis labels in the second column
new.y.label.grob <- gtable_add_cols(new.y.label.grob,
widths = y.label.grob[["widths"]][1])
new.y.label.grob <- gtable_add_grob(new.y.label.grob,
y.label.grob[["grobs"]][[1]],
t = 1, l = 2)
# add third column that takes up all the remaining space
new.y.label.grob <- gtable_add_cols(new.y.label.grob,
widths = unit(1, "null"))
在与绘图区域相同的位置,将新定义的y轴标签grob重新添加到绘图grob中:
Add the newly defined y-axis label grob back to the plot grob, in the same location as the plot area:
gp <- gtable_add_grob(gp,
new.y.label.grob,
t = gp$layout$t[which(gp$layout$name == "panel")],
l = gp$layout$l[which(gp$layout$name == "panel")])
检查结果:
grid.draw(gp)
这篇关于ggplot2:y轴标签在绘图区域内左对齐的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!