Home > Enterprise >  Remove segment around label/text
Remove segment around label/text

Time:10-16

Consider a plot with a segment/line and a text/label. I'd like the text to overlay the segment such that the text does not overlap the segment.

I tried using geom_label but I still want the background to be the same, just the other objects to be removed around the text. I also tried with geomtextpath but couldn't get the text to be horizontal. Any ideas?

seg <- data.frame(x = 1, xend = 1, y = 2, yend = 3)
plot1 <- ggplot(seg)  
  aes(x = x, xend = xend, y = y, yend = yend)  
  geom_segment()  
  geom_text(aes(y = (y   yend) / 2), label = "Hello", size = 10)  
  labs(title = "geom_text", 
       subtitle = "The text is horizontal but the segment should\nbe cut around the text.")

library(geomtextpath)
plot2 <- ggplot(seg)  
  aes(x = x, xend = xend, y = y, yend = yend)  
  geom_textsegment(label = "Hello", size = 10)  
  labs(title = "geomtextpath",
       subtitle = "The segment is correctly overlaid but\nI need the text to be horizontal")

seg2 <- data.frame(x = c(1, 1), xend = c(1, 1), y = c(2, 2.55), yend = c(2.45, 3))
plot3 <- ggplot(seg2)  
  aes(x = x, xend = xend, y = y, yend = yend)  
  geom_segment()  
  geom_text(aes(y = 2.5), label = "Hello", size = 10)  
  labs(title = "manual geom_segment", 
       subtitle = "This is the expected output, but it is done\nmanually. I need a scalable solution.")

library(patchwork)
plot1   plot2   plot3

enter image description here

CodePudding user response:

I wouldn't say the following is 'easy', but you can use the {ggfx} package to put an inverted mask on the segment that corresponds with a textbox.

library(ggplot2)
library(ggfx)

seg <- data.frame(x = 1, xend = 1, y = 2, yend = 3)

ggplot(seg)  
  aes(x = x, xend = xend, y = y, yend = yend)  
  # Adding a label-textbox as mask ensures appropriate window-agnostic size
  # Just make sure the aesthetics are the same as the geom_text later
  as_reference(
    geom_label(aes(y = (y   yend) / 2), label = "Hello", size = 10),
    id = "textbox"
  )  
  # Plot the masked bit
  with_mask(
    geom_segment(),
    mask = ch_alpha("textbox"), invert = TRUE
  )  
  # On top of the mask
  geom_text(aes(y = (y   yend) / 2), label = "Hello", size = 10)

Created on 2022-10-14 by the reprex package (v2.0.1)

CodePudding user response:

An option could be using ggplot_build to modify the distance of your geom_segment by creating two separate segments like this:

seg <- data.frame(x = 1, xend = 1, y = 2, yend = 3)

library(ggplot2)
library(dplyr)
p <- ggplot(seg)  
  aes(x = x, xend = xend, y = y, yend = yend)  
  geom_segment()  
  geom_text(aes(y = (y   yend) / 2), label = "Hello", size = 10)

q <- ggplot_build(p)

q$data[[1]] <- q$data[[1]] %>%
  bind_rows(q$data[[1]]) %>%
  mutate(y = c(2, 2.55),
         yend = c(2.45, 3))

q <- ggplot_gtable(q)

plot(q)

Created on 2022-10-15 with reprex v2.0.2

  • Related