我正在研究类似于坡度图的图表,在该图表中,我想在标签的一侧或两侧放置标签,并留出足够的空白空间以使其在两侧都适合。在标签很长的情况下,我使用stringr::str_wrap了换行符来包装它们。为了防止标签重叠,我使用ggrepel::geom_text_repel,direction = "y"以便x位置稳定,而y位置相互排斥。我还必须hjust = "outward"将左侧文本的右端对齐,反之亦然。
但是,似乎排斥位置将标签的边界框放置为hjust = "outward",但是该标签内的文本具有hjust = 0.5,即文本在其边界内居中。到现在为止,我还没有注意到这一点,但是在包裹标签的情况下,第二行居中居中,而我希望这两行都左对齐或右对齐。
这是基于mpg数据集构建的示例。
library(ggplot2)
library(dplyr)
library(ggrepel)
df <- structure(list(long_lbl = c("chevrolet, k1500 tahoe 4wd, auto(l4)",
"chevrolet, k1500 tahoe 4wd, auto(l4)", "subaru, forester awd, manual(m5)",
"subaru, forester awd, manual(m5)", "toyota, camry, manual(m5)",
"toyota, camry, manual(m5)", "toyota, toyota tacoma 4wd, manual(m5)",
"toyota, toyota tacoma 4wd, manual(m5)", "volkswagen, jetta, manual(m5)",
"volkswagen, jetta, manual(m5)"), year = c(1999L, 2008L, 1999L,
2008L, 1999L, 2008L, 1999L, 2008L, 1999L, 2008L), mean_cty = c(11,
14, 18, 20, 21, 21, 15, 17, 33, 21)), class = c("tbl_df", "tbl",
"data.frame"), row.names = c(NA, -10L))
df_wrap <- df %>%
mutate(wrap_lbl = stringr::str_wrap(long_lbl, width = 25))
ggplot(df_wrap, aes(x = year, y = mean_cty, group = long_lbl)) +
geom_line() +
geom_text_repel(aes(label = wrap_lbl),
direction = "y", hjust = "outward", seed = 57, min.segment.length = 100) +
scale_x_continuous(expand = expand_scale(add = 10))
Run Code Online (Sandbox Code Playgroud)

的其他值也会发生相同的情况hjust。查看函数的源代码,我看到一行指出了这个问题:
hjust = x$data$hjust %||% 0.5,
Run Code Online (Sandbox Code Playgroud)
%||%如果x$data$hjust为null ,则分配0.5 。据我所知,但这似乎hjust并没有被我设置为该位置,而是变为null。
我错过了什么吗?任何人都可以看到我可以在不重新实现整个算法的情况下覆盖它的地方吗?还是这里有个让我掉落的错误hjust?
TL; DR:可能是一个错误
长答案:
我认为这可能是代码中的错误。我检查了您制作的图的gtable,其中hjust数字是正确指定的:
# Assume 'g' is the plot saved under the variable 'g'
gt <- ggplotGrob(g)
# Your number at the end of the geom may vary
textgrob <- gt$grobs[[6]]$children$geom_text_repel.textrepeltree.1578
head(textgrob$data$hjust)
Run Code Online (Sandbox Code Playgroud)
[1] 1 0 1 0 1 0
Run Code Online (Sandbox Code Playgroud)
这让我想到(1)无法通过在gtable中弄乱来固定绘图,以及(2)grob textrepeltree类的绘图时间代码可能包含一些错误。这是有道理的,因为在调整绘图设备的大小时会重新放置标签。因此,当我们查看makeContent.textrepeltree()您提供的链接中的代码时,我们可以看到hjust参数传递给makeTextRepelGrobs()。让我们看一下相关的形式:
makeTextRepelGrobs <- function(
...other_arguments...,
just = "center",
...other_arguments...,
hjust = 0.5,
vjust = 0.5
) { ...body...}
Run Code Online (Sandbox Code Playgroud)
我们可以看到,这hjust是一个有效的参数,但是也存在一个just参数,该参数不是从传递的makeContent.textrepeltree()。
当我们查看函数体时,有以下两行:
hj <- resolveHJust(just, NULL)
vj <- resolveVJust(just, NULL)
Run Code Online (Sandbox Code Playgroud)
从哪里resolveH/VJust导入了网格包。在resolveHJust()本质上检查是否第二个参数是NULL,如果这是真的,默认为第一个参数,否则返回第二个参数。您可以看到hjust传递给的makeTextRepelGrobs()不会传递给resolveHJust(),这似乎是您的hjust参数意外删除的地方。
在代码的最下方是实际的文本杂记:
t <- textGrob(
...other_arguments...
just = c(hj, vj),
...other_arguments...
)
Run Code Online (Sandbox Code Playgroud)
我认为解决方法相对简单:您只需要提供hjust作为的第二个参数即可resolveHJust()。但是,由于这makeTextRepelGrobs()是ggrepel的内部功能,并且不会导出,因此您必须复制很多额外的代码才能使其正常工作。(不确定是否仅复制即可makeTextRepelGrob(),还没有测试过)
所有这些使我得出的结论是hjust,您指定的in geom_text_repel()在绘制时间的最后时刻被makeTextRepelGrobs()内部函数丢失了。
| 归档时间: |
|
| 查看次数: |
149 次 |
| 最近记录: |