Adrian
Adrian

Reputation: 9793

How to use directlabels to label lines in ggplot2

library(ggplot2)
library(directlabels)
mydat <- structure(list(Name = c("Ana", "Josh", "Bart", "Ana", "Josh", 
"Bart"), color_line = c("purple", "purple", "orange", "purple", 
"purple", "orange"), x = c(0.864864864864865, 0.810810810810811, 
0.472972972972973, 0.851351351351351, 0.702702702702703, 0.648648648648649
), y = c(0.702702702702703, 0.675675675675676, 0.797297297297297, 
0.797297297297297, 0.72972972972973, 0.635135135135135), Class = c("A", 
"A", "A", "B", "B", "B")), class = c("data.table", "data.frame"
), row.names = c(NA, -6L))

mydat
   Name color_line         x         y Class
1:  Ana     purple 0.8648649 0.7027027     A
2: Josh     purple 0.8108108 0.6756757     A
3: Bart     orange 0.4729730 0.7972973     A
4:  Ana     purple 0.8513514 0.7972973     B
5: Josh     purple 0.7027027 0.7297297     B
6: Bart     orange 0.6486486 0.6351351     B

I have the above data set, and I plotted the results as follows:

g <- ggplot(mydat, aes(x = x, y = y, color = Class)) + 
       theme_classic() + 
       geom_line(mapping = aes(group = Name), color = mydat$color_line) + 
       geom_point() + 
       scale_color_manual(values=c("springgreen4", "royalblue3"))
g

enter image description here

Now, I would like to add the Name of each individual to each line. Something that might look like this:

enter image description here

The closest thing that I found is the angled.boxes in library(directlabels). You can see how it looks here.

However, when I tried the following, I got a different plot.

direct.label(g, "angled.boxes")

enter image description here

Upvotes: 0

Views: 281

Answers (2)

stefan
stefan

Reputation: 124148

One option to achieve your desired result would be to use the geomtextpath package which adds lots of options to add direct labels to lines and even allows for curved text. For your use case you could simply replace geom_line by geomtextpath::geom_textline to add your labels.

Note: Additionally I slightly adjusted your code to make use of the color aes for the lines and the fill aes to color the points.

library(ggplot2)
library(geomtextpath)

pal_color <- c("purple", "purple", "orange")
names(pal_color) <- c("Ana", "Josh", "Bart")

pal_fill <- c("springgreen4", "royalblue3")
names(pal_fill) <- c("A", "B")

base <- ggplot(mydat, aes(x = x, y = y)) + 
  scale_color_manual(values = pal_color) +
  scale_fill_manual(values= pal_fill) +
  theme_classic() +
  guides(color = "none")

base +
  geomtextpath::geom_textline(
    aes(group = Name, color = Name, label = Name), textcolour = "black") +
  geom_point(aes(fill = Class), shape = 21, stroke = 0, size = 2)

Or using the offset and gap arguments you could add the labels on top of the lines:

base +
  geomtextpath::geom_textline(
    aes(group = Name, color = Name, label = Name),
    offset = unit(5, "pt"), gap = FALSE, textcolour = "black") +
  geom_point(aes(fill = Class), shape = 21, stroke = 0, size = 2)

Upvotes: 4

Vin&#237;cius F&#233;lix
Vin&#237;cius F&#233;lix

Reputation: 8811

It's not ideal, but I did this a long time ago using some math and manual adjustments

mydat %>% 
  group_by(Name) %>% 
  mutate(
    posx = mean(x)*1.01,
    posy = mean(y)*1.01,
    angle = -60*diff(range(y))/diff(range(x))
    ) %>% 
  ggplot(aes(x = x, y = y, color = Class)) + theme_classic() +
  geom_line(mapping = aes(group = Name), color = mydat$color_line) +
  geom_point() + scale_color_manual(values=c("springgreen4", "royalblue3"))+
  geom_text(aes(x = posx, y = posy, group = Name, label = Name, angle = angle),
            size = 6, show.legend = FALSE, color = "black")

enter image description here

Upvotes: 0

Related Questions