在文本框中包装长文本

时间:2018-04-10 14:39:02

标签: r ggplot2 ggrepel

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

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

enter image description here

我希望标签位于点之上,并且限制为更小的xlim aka宽度。有没有办法在ggplot2ggrepel中包装文本或生成某种文本框以使此功能成为可能?

2 个答案:

答案 0 :(得分:2)

这是一个自定义函数,可用于在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()

答案 1 :(得分:1)

你可以使用这个虚拟函数,用\n50字符替换空格。

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

enter image description here

PS:如果只有一个长字(> 50个字符),它将无效。