将长文本换行在文本框中

Wrap long text in a text box

我有以下可重现的系数图。

library(tidyverse)
tribble(~term, ~estimate, ~lower, ~upper, ~text,
        "a", .25, .2, .3 , "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur sit amet orci vel dolor luctus auctor sed non lacus. Cras malesuada, tortor ac mattis rutrum, dui erat aliquam ipsum, id.",
        "b", -.25, -.3, -.2, "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur sit amet orci vel dolor luctus auctor sed non lacus. Cras malesuada, tortor ac mattis rutrum, dui erat aliquam ipsum, id.",
        "intercept",0, -.1, .1, NA) %>% 
  ggplot(aes(y = term, x = estimate, label = text)) +
  geom_point() +
  ggrepel::geom_text_repel(size = 2, label.size = 0.1) +
  geom_errorbarh(aes(xmin = lower, xmax = upper), height = 0) +
  geom_vline(aes(xintercept = 0), linetype = "dashed") +
  theme_classic()

我希望标签位于点上方并限制为较小的 xlim 宽度。有没有办法在 ggplot2ggrepel 中换行或生成某种文本框来实现此功能?

您可以使用这个虚拟函数,每隔 50 个字符将 space 替换为 \n

library(tidyverse)
data <- tribble(~term, ~estimate, ~lower, ~upper, ~text,
        "a", .25, .2, .3 , "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur sit amet orci vel dolor luctus auctor sed non lacus. Cras malesuada, tortor ac mattis rutrum, dui erat aliquam ipsum, id.",
        "b", -.25, -.3, -.2, "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur sit amet orci vel dolor luctus auctor sed non lacus. Cras malesuada, tortor ac mattis rutrum, dui erat aliquam ipsum, id.",
        "intercept",0, -.1, .1, "Lorem impsum")

data$textBreaks <- sapply(strsplit(data$text, " "), function(x) {
    spacePosition <- cumsum(nchar(x))
    placeBreak <- spacePosition[which(diff(spacePosition %/% 50) == 1)] + 1
    result <- paste(x, collapse = " ")
    for(i in placeBreak) {
        substring(result, i, i) <- "\n"
    }
    result
})
ggplot(data, aes(estimate, term,label = textBreaks)) +
    geom_point() +
    ggrepel::geom_text_repel(size = 2) +
    geom_errorbarh(aes(xmin = lower, xmax = upper), height = 0) +
    geom_vline(aes(xintercept = 0), linetype = "dashed") +
    theme_classic()

PS.: 如果只有一个长字(> 50个字符)就不行了。

这是一个自定义函数,您可以使用它在 N 个字符后插入换行符(最近的空格将被换行符替换):

library(stringr)

wrap_text <- function(string, n) {
  spaces <- str_locate_all(string, " ")[[1]][,1]
  chars  <- nchar(string)
  for(i in 1:floor(chars/n)) {
    s <- spaces[which.min(abs(spaces - n*i))]
    substring(string, s, s) <- "\n "
  }
  return(string)
}

tribble(~term, ~estimate, ~lower, ~upper, ~text,
        "a", .25, .2, .3 , "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur sit amet orci vel dolor luctus auctor sed non lacus. Cras malesuada, tortor ac mattis rutrum, dui erat aliquam ipsum, id.",
        "b", -.25, -.3, -.2, "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur sit amet orci vel dolor luctus auctor sed non lacus. Cras malesuada, tortor ac mattis rutrum, dui erat aliquam ipsum, id.",
        "intercept",0, -.1, .1, NA) %>% 
  ggplot(aes(y = term, x = estimate, label = I(wrap_text(text, nw = 30)))) +
  geom_point() +
  ggrepel::geom_text_repel(size = 2, label.size = 0.1) +
  geom_errorbarh(aes(xmin = lower, xmax = upper), height = 0) +
  geom_vline(aes(xintercept = 0), linetype = "dashed") +
  theme_classic()