John Doe
John Doe

Reputation: 145

Connect start and end between groups within segmented lines in R?

My data frame looks as follows:

> df
  person step start end
1    sam    A     0   4
2    sam    B     4   6
3   greg    A     2   7
4   greg    B     7  11

And I plot the following chart:

library(ggplot2)
library(dplyr)
library(tidyr)

ggplot(df, aes(colour=step)) + 
  geom_segment(aes(x=start, xend=end, y=person, yend=person), size=3) +
  xlab("Duration")

Now, I want to connect each start and end between sam and greg and label it with the difference.

The expected graphic should look something like this:

enter image description here

The problem is that I don't know how I can draw the lines without passing x and y coordinates. The y coordinates are determined by the grouping (person).

Upvotes: 0

Views: 174

Answers (2)

jazzurro
jazzurro

Reputation: 23574

I followed your way and wrote the following code. The key thing is that you need to transform your data so that you can draw lines and labels. For the lines, I used geom_segment(). The function requires x, xend, y, and yend. So I generated these values. For the labels, I used geom_text(), and I needed to generate x, y, and label.

library(tidyverse)

# This data transformation is for drawing lines between Greg and Sam

df2 <- gather(df, key = whatever, value = value, -person, -step) %>%
       group_by(person) %>%
       distinct(value) %>%
       arrange(person, value) %>%
       mutate(group = 1:n()) %>%
       spread(key = person, value = value) %>%
       mutate(y = 2, yend = 1)

# This data transformation is for labels

df3 <- mutate(df2, x = (greg + sam) / 2 + 0.4, y = 1.5,
              label = greg - sam)

ggplot(df, aes(colour = step)) + 
geom_segment(aes(x = start, xend = end, y = person, yend = person), size = 3) +
geom_segment(data = df2, aes(x = sam, xend = greg, y = y, yend = yend),
             size = 2, lineend = "round", inherit.aes = F) +
geom_text(data = df3, aes(x = x, y = y, label = label), inherit.aes = F) +
xlab("Duration") 

enter image description here

DATA

df <- structure(list(person = c("sam", "sam", "greg", "greg"), step = c("A", 
"B", "A", "B"), start = c(0L, 4L, 2L, 7L), end = c(4L, 6L, 7L, 
11L)), .Names = c("person", "step", "start", "end"), class = "data.frame", row.names = c("1", 
"2", "3", "4"))

Upvotes: 1

Andre Elrico
Andre Elrico

Reputation: 11480

Not a complete answer but this should get you to your goal:

your Data:

df<-
fread("person step start end
sam    A     0   4
sam    B     4   6
greg    A     2   7
greg    B     7  11")

Your main task is to find/calculate data1:

data1 <- data.frame(x=2:4,xend=1:3,y=rep(1,3),yend=rep(2,3),textx=1:3+.5,texty=rep(1.5,3),textlabel=letters[1:3])

add the info of data1:

ggplot(df, aes(colour=step)) + 
    geom_segment(aes(x=start, xend=end, y=person, yend=person), size=3) +
    xlab("Duration") +
    geom_segment(data = data1,aes(x = x, y = y, xend = xend, yend = yend),colour="black",size=3) +
    geom_text(data = data1,aes(x = textx+0.5, y = texty, label=textlabel),colour="green",size=7)

plot: enter image description here

please note:

sam and greg are stored as factors and therefore integer values from 1 to n.

  1. this means greg is 1 and sam is 2. (by default factors are sorted alphabetically)

  2. this means the y position between greg and sam is 1.5

Upvotes: 1

Related Questions