Graphing attendance at event with join and leave times

I have attendance data from an online event where each row contains an email address, a join time, and a leave time. Some attendees have multiple rows since they joined, left, and then re-joined the meeting (sometimes several times). There were approximately 200 attendees over the course of the ~90 minute event. I want to create a visualization that shows when attendees joined and left over the course of the whole event. I'm thinking a graph where each attendee's join and leave times are plotted so that each attendee has a single line. I don't know where to begin and am hoping for any recommendations. Thanks! Here's a sample of what my data looks like:

structure(list(Email= c("email1@gmail.com", "email2@gmail.com", "email2@gmail.com", 
"email3@gmail.com","email3@gmail.com"), Join.Time = structure(c(as.POSIXct("2020-12-09 13:04:00"), 
as.POSIXct("2020-12-09 13:20:00"), as.POSIXct("2020-12-09 13:30:00"),as.POSIXct("2020-12-09 13:07:00"),
as.POSIXct("2020-12-09 13:29:00")), class = c("POSIXct", "POSIXt"),tzone = "America/New_York"), 
Leave.Time = structure(c(as.POSIXct("2020-12-09 13:25:00"), as.POSIXct("2020-12-09 13:22:00"), 
as.POSIXct("2020-12-09 14:01:00"), as.POSIXct("2020-12-09 13:29:00"), as.POSIXct("2020-12-09 14:33:00")), 
class = c("POSIXct", "POSIXt"), tzone = "America/New_York")),.Names = c("Email", "Join.Time", "Leave.Time"), 
row.names = c(NA, -5L), class = "data.frame")
suppressPackageStartupMessages({
  library(vistime)
})

DF <- data.frame(
  Event = c(1,1,1,1,1),
  Email = c(
    "email1@gmail.com", "email2@gmail.com", "email2@gmail.com",
    "email3@gmail.com", "email3@gmail.com"
  ), 
  Join.Time = c(
    as.POSIXct("2020-12-09 13:04:00"),
    as.POSIXct("2020-12-09 13:20:00"), 
    as.POSIXct("2020-12-09 13:30:00"),
    as.POSIXct("2020-12-09 13:07:00"),
    as.POSIXct("2020-12-09 13:29:00")),
  Leave.Time =c(
    as.POSIXct("2020-12-09 13:25:00"),
    as.POSIXct("2020-12-09 13:22:00"),
    as.POSIXct("2020-12-09 14:01:00"), 
    as.POSIXct("2020-12-09 13:29:00"), 
    as.POSIXct("2020-12-09 14:33:00")))

DF

vistime(DF,
  col.event = "Event", 
  col.start = "Join.Time", 
  col.end = "Leave.Time", 
  col.group = "Email")

Hi @maggiebm,

This might serve as a starting point:

library(tidyverse)

data <- structure(list(Email= c("email1@gmail.com", "email2@gmail.com", "email3@gmail.com", 
                                "email4@gmail.com","email5@gmail.com"), Join.Time = structure(c(as.POSIXct("2020-12-09 13:04:00"), 
                                                                                                as.POSIXct("2020-12-09 13:20:00"), as.POSIXct("2020-12-09 13:30:00"),as.POSIXct("2020-12-09 13:07:00"),
                                                                                                as.POSIXct("2020-12-09 13:29:00")), class = c("POSIXct", "POSIXt"),tzone = "America/New_York"), 
                       Leave.Time = structure(c(as.POSIXct("2020-12-09 13:25:00"), as.POSIXct("2020-12-09 13:22:00"), 
                                                as.POSIXct("2020-12-09 14:01:00"), as.POSIXct("2020-12-09 13:29:00"), as.POSIXct("2020-12-09 14:33:00")), 
                                              class = c("POSIXct", "POSIXt"), tzone = "America/New_York")),.Names = c("Email", "Join.Time", "Leave.Time"), 
                  row.names = c(NA, -5L), class = "data.frame") %>% 
  as_tibble()


data %>% 
  ggplot(aes(y = Email, color = Email)) +
  geom_point(aes(x = Join.Time), size = 3) +
  geom_point(aes(x = Leave.Time), size = 3) +
  geom_segment(aes(x = Join.Time, xend = Leave.Time,
                   y = Email, yend = Email), size = 1) +
  labs(x = "Time", y = "") +
  theme_light() +
  theme(
    text = element_text(size = 14),
    legend.position = "none"
  )

1 Like

Better than what I suggested.

@technocrat I wasn't trying to step on your toes. I submitted my response several days ago but for some reason it sat in purgatory while awaiting approval.

1 Like

Ah, we both fell into the dreaded email address bot. My toes are fine‐your solution is what I gave up before resorting to an off-brand. Your solution went into my snip vault.

1 Like

Thank you both! While I like the visuals the 2nd one, unfortunately that one seems to treat each row as a unique person, when we have multiple people that log off and then back on. The first one seems to handle that well.

Thats actually a consequence of me trying to be clever. I thought it was a copy-and-paste error that emails were duplicated so I de-duplicated them. That was a mistake on my part.

1 Like
library(tidyverse)

data <- structure(list(Email= c("email1", "email2", "email2", 
                                "email3","email3"), Join.Time = structure(c(as.POSIXct("2020-12-09 13:04:00"), 
                                                                            as.POSIXct("2020-12-09 13:20:00"), as.POSIXct("2020-12-09 13:30:00"),as.POSIXct("2020-12-09 13:07:00"),
                                                                            as.POSIXct("2020-12-09 13:29:00")), class = c("POSIXct", "POSIXt"),tzone = "America/New_York"), 
                       Leave.Time = structure(c(as.POSIXct("2020-12-09 13:25:00"), as.POSIXct("2020-12-09 13:22:00"), 
                                                as.POSIXct("2020-12-09 14:01:00"), as.POSIXct("2020-12-09 13:29:00"), as.POSIXct("2020-12-09 14:33:00")), 
                                              class = c("POSIXct", "POSIXt"), tzone = "America/New_York")),.Names = c("Email", "Join.Time", "Leave.Time"), 
                  row.names = c(NA, -5L), class = "data.frame") %>% 
  as_tibble()


data %>% 
  ggplot(aes(y = Email, color = Email)) +
  geom_point(aes(x = Join.Time), size = 3) +
  geom_point(aes(x = Leave.Time), size = 3) +
  geom_segment(aes(x = Join.Time, xend = Leave.Time,
                   y = Email, yend = Email), size = 1) +
  labs(x = "Time", y = "") +
  theme_light() +
  theme(
    text = element_text(size = 14),
    legend.position = "none"
  )