Search code examples
rggplot2geom-segment

Phase diagram with vertical lines connecting discrete phases or states


I draw a state diagram using ggplot2 in R. The discrete vertical axis shows several states, and the horizontal axis shows time. Lines connect the start and end points of a phase, with different colours per state. Here is an example:

library("ggplot2")

states <- data.frame(state = factor(c(2, 1, 2, 1)),
                     start = c(0.5, 1.5, 3.5, 5.5),
                     end = c(1.5, 3.5, 5.5, 7.5))

ggplot(states, aes(x = start,
                   xend = end,
                   y = state,
                   yend = state,
                   color = state)) + 
  geom_segment(size = 3)

enter image description here

How can I connect the end point of a phase with the start point of the next phase (in a different state) using a black, vertical line? Each time point has exactly one state, i.e., there are no overlapping states and no empty time points.


Solution

  • One option would be to reshape your data to long and use the group aes to draw the segments as well as the connecting lines via geom_line:

    library(ggplot2)
    library(dplyr, warn=FALSE)
    library(tidyr)
    
    states1 <- states |> 
      mutate(id = row_number()) |> 
      pivot_longer(c(start, end))
      
    ggplot(states1, aes(
      x = value,
      y = state,
      color = state,
    )) +
      geom_line(aes(group = value),
        color = "black",
        linewidth = 3, lineend = "round"
      ) +
      geom_line(aes(group = id), linewidth = 3, lineend = "round")
    

    enter image description here