问题
I have the following reproducible coefficient plot.
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()
I would like the labels to be above the points and limited to a smaller xlim aka width. Is there a way to wrap text or generate some kind of text box in ggplot2
or ggrepel
to make this functionality possible?
回答1:
You can use this dummy function that replaces space with \n
every 50
characters.
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.: It won't work if there's only one long word (> 50 characters).
回答2:
Here is a custom function that you might use to insert line breaks after N
chars (closest spaces will be replaced by the line break):
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()
来源:https://stackoverflow.com/questions/49756457/wrap-long-text-in-a-text-box