我正在制作类似于坡度图的图表,在该图表中,我想在标签的一侧或两侧放置标签,并留出足够的空白以使其在两侧都适合。在标签很长的情况下,我使用stringr::str_wrap包裹了换行符。为了防止标签重叠,我在ggrepel::geom_text_repeldirection = "y"中使用了hjust = "outward",因此x位置是稳定的,而y位置却相互排斥。我还用hjust = "outward"将左侧文本的右端对齐,反之亦然。

但是,似乎排斥位置将标签的边界框放置为hjust = 0.5,但是该标签内的文本具有mpg,即文本在其边界内居中。到现在为止,我还没有注意到这一点,但是在包裹了标签的情况下,第二行居中居中,而我希望这两行都左对齐或右对齐。

这是基于hjust数据集构建的示例。



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))




其他%||%值也会发生相同的情况。查看函数的source,我看到一行指出了这个问题:

hjust = x$data$hjust %||% 0.5,


如果x$data$hjust为null,则hjust分配0.5。据我所知,但是我设置的hjust似乎并没有延续到这个位置,而是变为null。

我错过了什么吗?任何人都可以看到我可以在不重新实现整个算法的情况下覆盖它的地方吗?还是这里有一个错误使我的掉线?

最佳答案

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)


[1] 1 0 1 0 1 0


这让我想到(1)无法通过在gtable中弄乱来固定绘图,以及(2)grobs的textrepeltree类的绘图时间代码可能包含一些错误。这是有道理的,因为在调整绘图设备的大小时会重新放置标签。因此,当我们查看您提供的链接中的makeContent.textrepeltree()代码时,我们可以看到hjust参数被传递给makeTextRepelGrobs()。让我们看一下相关的形式:

makeTextRepelGrobs <- function(
  ...other_arguments...,
  just = "center",
  ...other_arguments...,
  hjust = 0.5,
  vjust = 0.5
) { ...body...}


我们可以看到hjust是有效的参数,但是还存在just参数,该参数不是从makeContent.textrepeltree()传递的参数。

当我们看一下函数体时,有以下两行:

  hj <- resolveHJust(just, NULL)
  vj <- resolveVJust(just, NULL)


从网格包中导入的resolveH/VJustresolveHJust()本质上检查第二个参数是否为NULL,如果为true,则默认为第一个参数,否则返回第二个参数。您可以看到传递给hjustmakeTextRepelGrobs()未被传递给resolveHJust(),这似乎是意外地删除了hjust参数的地方。

在代码的最下方是实际的文本杂记:

  t <- textGrob(
    ...other_arguments...
    just = c(hj, vj),
    ...other_arguments...
  )


我认为解决方法相对简单:您只需提供hjust作为resolveHJust()的第二个参数。但是,由于makeTextRepelGrobs()是ggrepel内部的,并且不会导出,因此您必须复制很多额外的代码才能使它起作用。 (不确定是否仅复制makeTextRepelGrob()就足够了,还没有测试过)

所有这些使我得出的结论是,在hjust中指定的geom_text_repel()在绘制时间的最后时刻被makeTextRepelGrobs()内部函数丢失了。

关于r - 使用ggrepel覆盖水平定位,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/56028991/

10-12 19:40