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)
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.
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")