使用 ggplot 绘制绘图时,hjust 和 vjust 做了啥?

Posted

技术标签:

【中文标题】使用 ggplot 绘制绘图时,hjust 和 vjust 做了啥?【英文标题】:What do hjust and vjust do when making a plot using ggplot?使用 ggplot 绘制绘图时,hjust 和 vjust 做了什么? 【发布时间】:2011-11-07 23:53:58 【问题描述】:

每次我使用 ggplot 绘制绘图时,我都会花一点时间尝试不同的 hjust 和 vjust 值,例如

+ opts(axis.text.x = theme_text(hjust = 0.5))

让轴标签在轴标签几乎接触轴的位置对齐,并与轴齐平(可以说是与轴对齐)。但是,我真的不明白发生了什么。例如,hjust = 0.5 给出的结果通常与hjust = 0.6 截然不同,以至于我无法仅通过使用不同的值来弄清楚。

谁能指出我对 hjust 和 vjust 选项如何工作的全面解释?

【问题讨论】:

我确实给出了一个具体的例子,在第一个答案的 cmets 中。显然使用 0-1 之外的数字是未定义的,如果不解释为什么 hjust=-1 有奇怪的行为,至少可以解释奇怪是可以预料的。 【参考方案1】:

hjustvjust 的值只定义在 0 和 1 之间:

0 表示左对齐 1 表示右对齐

来源:ggplot2,Hadley Wickham,第 196 页

(是的,我知道在大多数情况下,您可以在此范围之外使用它,但不要期望它以任何特定方式运行。这超出了规范。)

hjust 控制水平对齐,vjust 控制垂直对齐。

一个例子应该清楚地说明这一点:

td <- expand.grid(
    hjust=c(0, 0.5, 1),
    vjust=c(0, 0.5, 1),
    angle=c(0, 45, 90),
    text="text"
)

ggplot(td, aes(x=hjust, y=vjust)) + 
    geom_point() +
    geom_text(aes(label=text, angle=angle, hjust=hjust, vjust=vjust)) + 
    facet_grid(~angle) +
    scale_x_continuous(breaks=c(0, 0.5, 1), expand=c(0, 0.2)) +
    scale_y_continuous(breaks=c(0, 0.5, 1), expand=c(0, 0.2))


要了解在轴文本中更改 hjust 时会发生什么,您需要了解轴文本的水平对齐方式不是相对于 x 轴,而是相对于整个绘图(其中包括y 轴文本)。 (在我看来,这是不幸的。相对于轴对齐会更有用。)

DF <- data.frame(x=LETTERS[1:3],y=1:3)
p <- ggplot(DF, aes(x,y)) + geom_point() + 
    ylab("Very long label for y") +
    theme(axis.title.y=element_text(angle=0))


p1 <- p + theme(axis.title.x=element_text(hjust=0)) + xlab("X-axis at hjust=0")
p2 <- p + theme(axis.title.x=element_text(hjust=0.5)) + xlab("X-axis at hjust=0.5")
p3 <- p + theme(axis.title.x=element_text(hjust=1)) + xlab("X-axis at hjust=1")

library(ggExtra)
align.plots(p1, p2, p3)


要探索vjust 轴标签对齐会发生什么:

DF <- data.frame(x=c("a\na","b","cdefghijk","l"),y=1:4)
p <- ggplot(DF, aes(x,y)) + geom_point()

p1 <- p + theme(axis.text.x=element_text(vjust=0, colour="red")) + 
        xlab("X-axis labels aligned with vjust=0")
p2 <- p + theme(axis.text.x=element_text(vjust=0.5, colour="red")) + 
        xlab("X-axis labels aligned with vjust=0.5")
p3 <- p + theme(axis.text.x=element_text(vjust=1, colour="red")) + 
        xlab("X-axis labels aligned with vjust=1")


library(ggExtra)
align.plots(p1, p2, p3)

【讨论】:

因此对于角度 = 45 的情况,当我有不同长度的轴标签时,比如说从 25 到 5 个字符,它们既不会对齐到单词边界的右侧或左侧.看看坐标轴here 如果我使用 angle=45,我如何让它们右对齐并与坐标轴齐平? 我已经尝试过了,我得到了Error in grid.Call("L_textBounds", as.graphicsAnnot(x$label), x$x, x$y, : Polygon edge not found (zero-width or zero-height?) for vjust = .72 和更高版本。 @WilliamGunn 我建议你用你的代码发布一个新问题。 由于 opt 已被弃用,我们如何调整轴标题的位置? @CyrusMohammadian,我已经编辑了这个答案以使用当前的 ggplot2 语法。【参考方案2】:

可能最权威的是ggplot2书的图B.1(d),其附录可在http://ggplot2.org/book/appendices.pdf获得。

然而,事情并不是那么简单。 hjustvjust 如上所述,它在 geom_texttheme_text (有时)中是如何工作的。考虑它的一种方法是考虑文本周围的一个框,以及参考点相对于该框的位置,以相对于框的大小为单位(因此对于不同大小的文本不同)。一个 0.5 的 hjust 和一个 0.5 的 vjust 使框在参考点上居中。减少hjust 将框向右移动框宽度乘以0.5-hjust 的量。因此,当hjust=0 时,框的左边缘位于参考点。增加hjust 将框向左移动框宽度乘以hjust-0.5。当hjust=1 时,盒子从中心向左移动半个盒子宽度,这会将右边缘放在参考点上。如果hjust=2,框的右边缘是参考点左侧的框宽度(中心是参考点左侧的2-0.5=1.5框宽度。对于垂直,更少向上,更多向下。这实际上是图 B.1(d) 表示,但它推断超出 [0,1]。

但是,有时这不起作用。例如

DF <- data.frame(x=c("a","b","cdefghijk","l"),y=1:4)
p <- ggplot(DF, aes(x,y)) + geom_point()

p + opts(axis.text.x=theme_text(vjust=0))
p + opts(axis.text.x=theme_text(vjust=1))
p + opts(axis.text.x=theme_text(vjust=2))

后三个图是相同的。我不知道为什么会这样。此外,如果文本被旋转,那么它会更复杂。考虑

p + opts(axis.text.x=theme_text(hjust=0, angle=90))
p + opts(axis.text.x=theme_text(hjust=0.5 angle=90))
p + opts(axis.text.x=theme_text(hjust=1, angle=90))
p + opts(axis.text.x=theme_text(hjust=2, angle=90))

第一个标签左对齐(相对于底部),第二个标签在某个盒子中居中,因此它们的中心对齐,第三个标签右对齐(因此它们的右侧对齐轴)。最后一个,好吧,我无法以连贯的方式解释。它与文本的大小,最宽文本的大小有关,我不确定还有什么。

【讨论】:

非常感谢,这有助于角度 = 90 的情况,但我不明白为什么标签的右对齐不再起作用而不是角度 = 90 ,我使用角度=45。我理解 angle=45, hjust=0 的行为,但是 angle=45, hjust=-1 的行为很奇怪。 您的第一个示例确实有效。您认为它不起作用的原因是因为您所有的标签都具有相同的高度。使用DF &lt;- data.frame(x=c("a\na","b","cdefghijk","l"),y=1:4) 再试一次 - 即在其中一个标题中使用\n 换行符。 @William,我认为@Andrie 说得对; hjustvjust 只定义在 0 和 1 之间;超出该范围的行为没有意义。 @Andrie,你是对的。但是我仍然很难在轴标题/文本案例中建立一个连贯的心理模型。对于轴文本,hjust=0 将左边缘与 tic 对齐; hjust=0.5 以抽动为中心; hjust=1 将右边缘与 tic(相对于参考点的移动框)对齐。但是vjust一个与最高标签大小相同的框内对齐。 @BrianDiggs 在vjust 轴标签的情况下,所有标签同时相互对齐。因此,当vjust=1 时所有顶部边缘对齐,vjust=0 时所有底部边缘对齐。这对我来说很有意义。

以上是关于使用 ggplot 绘制绘图时,hjust 和 vjust 做了啥?的主要内容,如果未能解决你的问题,请参考以下文章

R语言ggplot2可视化使用vjust和hjust参数对齐图像中的文本注释信息(左对齐右对齐居中)实战

text ggplot2 vjust hjust标签

在 ggplot2 中使用 scale_color_manual 时,绘图中的中断和值不匹配

用 plotly 绘制多个 ggplot2 绘图

在ggplot中,如何在左对齐的同时将文本定位在最右端?

使用和不使用 ggplot 的交互式 R Shiny 绘图