{
  "$type": "site.standard.document",
  "content": "---\ntitle: \"Pulling apart Zoom attendance csv dumps in tidy R\"\ndescription: \"A quick tidyverse R script for parsing Zoom attendance CSVs and visualising\n  per-participant call duration with ggplot2.\"\ntags:\n  - dev\n---\n\nMy team ran some Zoom training last week and today I needed to figure out who\nactually attended across all the days, and for how long.\n\nZoom can give you a csv dump of all attendees but doesn't provide the\naggregations I was after, so I hacked up a little script (in\n[tidy R](https://www.tidyverse.org)) to do it. If you ever want to do something\nsimilar, feel free to use it ([MIT Licence](https://mit-license.org)).\n\n```r\nread_zoom_attendance_csv = function(filename){\n  read_csv(filename, show_col_types = FALSE) %>%\n    # I only needed the date, not the actual start time, so I didn't bother parsing\n    # the full datetime + timezone string that Zoom gives\n    mutate(date = parse_date(str_sub(`Join Time`, end = 10), format = \"%m/%d/%Y\")) %>%\n    # this isn't necessary, but I like shorter column names\n    rename(name = `Name (Original Name)`, email = `User Email`, duration = `Duration (Minutes)` ) %>%\n    # I'm only intrested in these columns\n    select(name, email, date, duration) %>%\n    # this isn't necessary, but handy if individuals have signed in with\n    # slightly different names on different days (requires eyeballing the data)\n    mutate(name = recode(name,\n                         \"JS\" = \"Joanna Smith\",\n                         \"Louise\" = \"Louise Jones\"\n}\n```\n\nThen you can read the Zoom csv file like so:\n\n```r\ndf = read_zoom_attendance_csv(\"zoom-call.csv\")\n```\n\nAnd to visualise in [ggplot2](https://ggplot2.tidyverse.org) (which was my\nreason for using R in the first place) you could try something like:\n\n```r\ndf %>%\n  group_by(name, date) %>%\n  # this was the key summarisation I was after - total time\n  # in-call across multiple connects/re-connects\n  summarise(duration = sum(duration)) %>%\n  ungroup() %>%\n  ggplot(aes(name, duration)) +\n  geom_col() +\n  coord_flip() +\n  facet_wrap(~date, nrow = 1) +\n  labs(\n    title = \"Zoom call attendance\",\n    x = \"participant name\",\n    y = \"duration on the call (minutes)\"\n  )\n```\n\nEnjoy!\n",
  "createdAt": "2026-05-13T23:14:49.074Z",
  "description": "A quick tidyverse R script for parsing Zoom attendance CSVs and visualising per-participant call duration with ggplot2.",
  "path": "/blog/2022/05/23/pulling-apart-zoom-attendance-csv-dumps-in-tidy-r",
  "publishedAt": "2022-05-23T00:00:00.000Z",
  "site": "at://did:plc:tevykrhi4kibtsipzci76d76/site.standard.publication/self",
  "tags": [
    "dev"
  ],
  "textContent": "A quick tidyverse R script for parsing Zoom attendance CSVs and visualising per-participant call duration with ggplot2.",
  "title": "Pulling apart Zoom attendance csv dumps in tidy R"
}