1

I have a list of time-ordered pairwise interactions. I want to plot a temporal network of these interactions, which would look something like the diagram below.

Temporal Network Example Image

My data looks like the example below. The id1 and id2 values are the unique identifiers of individuals. The time indicates when an interaction betweens those individuals occurred. So at time = 1, I want to plot a connection between individual-1 and individual-2.

id1 <- c(1, 2, 1, 6, 2, 2, 1)
id2 <- c(2, 4, 5, 7, 3, 4, 5)
time <- c(1, 2, 2, 2, 3, 4, 5)
df <- data.frame(id1, id2, time)

According to this StackOverflow question, I can see that it is possible to draw vertical lines between positions on the y-axis in ggplot. This is achieved by reshaping the data into a long format. This is fine when there is only one pair per time value, but not when there is more than one interacting pair at a time. For example in my dummy data, at time = 2, there are three pairs (in the plot I would show these by overlaying lines with reduced opacity).

My question is, how can I organise these data in a way that ggplot will be able to plot potentially multiple interacting pairs at specified time points?

I have been trying to reorganise the data by assigning an extra identifier to each of the multiple pairs that occur at the same time. I imagined the data table to look like this, but I haven't figure out how to make this in R... In this example the three interactions at time = 2 are identified by an extra grouping of either 1, 2 or 3. Even if I could arrange this I'm still not sure how I would get ggplot to read it.

Ultimately I'm trying to create someting that looks like Fig. 2 in this scientific paper.

Any help would be appreciated!

yrx1702
  • 1,619
  • 15
  • 27
Sam D.
  • 72
  • 10

2 Answers2

7

You can do this without reshaping the data, just set one id to y and the other id to yend in geom_curve:

ggplot(df, aes(x = time, y = id1)) +
    geom_curve(aes(xend = time, yend = id2), curvature = 0.3) +
    geom_hline(yintercept = 1:7, colour = scales::muted("blue")) +
    geom_point(size = 3) +
    geom_point(aes(y = id2), size = 3) +
    coord_cartesian(xlim = c(0, max(df$time) + 1)) +
    theme_bw()

Output:

enter image description here

Marius
  • 58,213
  • 16
  • 107
  • 105
2

Libraries:

library('ggplot2')
library('data.table')

Data:

id1 <- c(1, 2, 1, 6, 2, 2, 1)
id2 <- c(2, 4, 5, 7, 3, 4, 5)
time <- c(1, 2, 2, 2, 3, 4, 5)
df <- data.frame(id1, id2, time)
setDT(df)
df1 <- melt.data.table( df, id.vars = c('time'))

Plot:

p <- ggplot( df1, aes(time, value)) + 
  geom_point() + 
  geom_curve( mapping = aes(x = time, y = id1, xend = time, yend = id2, colour = "curve"), 
              data = df, 
              curvature = 0.2 )
print(p)

enter image description here

Sathish
  • 12,453
  • 3
  • 41
  • 59
  • Thanks this is great! I guess I was quite close but the reshaping was actually simpler than I realised. :) – Sam D. Nov 22 '17 at 22:35