Interactivity in charts

Lecture 20

Dr. Benjamin Soltoff

Cornell University
INFO 3312/5312 - Spring 2025

April 10, 2025

Announcements

Announcements

  • Project 02 proposals
  • Homework 05

Forms of interactivity

Forms of interactivity

Overview first, zoom and filter, then details on demand

  1. Present the most important figures or most relevant points to the audience
  2. Allow readers to dig into the information, explore, and come up with their own stories

Interactivity techniques

Storytelling form

  • Linear
  • Nonlinear

Interaction techniques

  • Scroll and pan
  • Zoom
  • Open and close
  • Sort and rearrange
  • Search and filter

Examples of interactive graphics

Communicating interactively with data

General approaches

  1. Interactive charts
  2. Scrollytelling
  3. Dashboards
  4. Interactive web applications

Interactive charts with Plotly

Interactive charts with Plotly

  • Open source software for creating graphs using JavaScript
  • Unlike D3.js, does not require extensive knowledge of JavaScript
  • ggplotly() converts {ggplot2} plots to {plotly} plots

Plotly

library(gapminder)
library(plotly)

gapminder_2007 <- filter(
  gapminder,
  year == 2007
)

my_plot <- ggplot(
  data = gapminder_2007,
  mapping = aes(
    x = gdpPercap, y = lifeExp,
    color = continent
  )
) +
  geom_point() +
  scale_x_log10() +
  theme_minimal()

ggplotly(my_plot)

Plotly

Plotly tooltips

my_plot <- ggplot(
  data = gapminder_2007,
  mapping = aes(
    x = gdpPercap, y = lifeExp,
    color = continent
  )
) +
  geom_point(mapping = aes(text = country)) +
  scale_x_log10() +
  theme_minimal()

ggplotly(
  my_plot,
  tooltip = "text"
)

Plotly tooltips

Works with most geoms

bm_hist <- ggplot(
  data = penguins,
  mapping = aes(x = body_mass_g)
) +
  geom_histogram(
    color = "white",
    binwidth = 100
  )

ggplotly(bm_hist)

Works with most geoms

Create a (basic) interactive chart with {ggplot2} and {plotly}

Get and clean data

library(tidyverse)
library(scales)
library(plotly)
library(colorspace)
library(ggbeeswarm)
# colors for the Democratic and Republican parties
dem <- "#00AEF3"
rep <- "#E81B23"

partisan_names <- read_csv(file = "data/partisan-names.csv") |>
  # convert year to a factor column for visualizations
  mutate(year = factor(year))

Static chart

Creating a basic interactive chart

static_plot <- ggplot(
  data = partisan_names,
  mapping = aes(
    x = part_diff,
    y = fct_rev(year),
    color = outcome
  )
) +
  geom_quasirandom() +
  scale_x_continuous(labels = label_percent(style_positive = "plus")) +
  scale_color_manual(values = c(dem, rep), guide = "none") +
  labs(
    title = "The most popular names have gotten more polarized",
    x = "Partisan gap",
    y = NULL,
    caption = '"Blue" and "red" state designations are based on the 2024 presidential election results.\nOnly names assigned at least 100 times in each year were included.\n\nSource: Social Security Administration'
  )
static_plot

Make it interactive

ggplotly(static_plot)

Make it interactive

Drawbacks to ggplotly()

  • Not everything translates to JavaScript
  • No caption
  • Legend has returned (must use theme(legend.position = "none"))

Modifying the tooltip

static_plot_tooltip <- ggplot(
  data = partisan_names,
  mapping = aes(
    x = part_diff,
    y = fct_rev(year),
    color = outcome
  )
) +
  geom_quasirandom(mapping = aes(text = name)) +
  scale_x_continuous(labels = label_percent(style_positive = "plus")) +
  scale_color_manual(values = c(dem, rep), guide = "none") +
  labs(
    title = "The most popular names have gotten more polarized",
    x = "Partisan gap",
    y = NULL,
  ) +
  theme(legend.position = "none")
static_plot_tooltip

Modifying the tooltip

ggplotly(static_plot_tooltip,
  tooltip = "text"
)

Modifying the tooltip

Including more information in the tooltip

  • Create a custom tooltip using the format:

    Year: Baby name
    +XX% R/D
  • Generate a new column using mutate() with the required HTML character string

    • str_glue() to combine character strings with data values
    • The <br> is HTML syntax for a line break
    • Use the label_percent() function to format numbers as percents

Create a custom tooltip

partisan_names <- partisan_names |>
  mutate(
    outcome = if_else(outcome == "Trump", "R", "D"),
    abs_part_diff = abs(part_diff),
    pct_label = label_percent(accuracy = 1, style_positive = 'plus')(abs_part_diff),
    fancy_label = str_glue("{year}: {name}<br>{pct_label} {outcome}")
  )
partisan_names |>
  select(year, part_diff, outcome, pct_label, fancy_label)
# A tibble: 200 × 5
   year  part_diff outcome pct_label fancy_label             
   <fct>     <dbl> <chr>   <chr>     <glue>                  
 1 1983      0.884 R       +88%      1983: Kendrick<br>+88% R
 2 1983      0.864 R       +86%      1983: Trey<br>+86% R    
 3 1983      0.854 R       +85%      1983: Rodrick<br>+85% R 
 4 1983      0.833 R       +83%      1983: Ashlea<br>+83% R  
 5 1983      0.780 R       +78%      1983: Tosha<br>+78% R   
 6 1983      0.773 R       +77%      1983: Misti<br>+77% R   
 7 1983      0.767 R       +77%      1983: Latoria<br>+77% R 
 8 1983      0.753 R       +75%      1983: Jackie<br>+75% R  
 9 1983      0.740 R       +74%      1983: Demarcus<br>+74% R
10 1983      0.737 R       +74%      1983: Angelia<br>+74% R 
# ℹ 190 more rows

Create a custom tooltip

static_plot_tooltip_fancy <- ggplot(
  data = partisan_names,
  mapping = aes(
    x = part_diff,
    y = fct_rev(year),
    color = outcome
  )
) +
  geom_quasirandom(mapping = aes(text = fancy_label)) +
  scale_x_continuous(labels = label_percent(style_positive = "plus")) +
  scale_color_manual(values = c(dem, rep), guide = "none") +
  labs(
    title = "The most popular names have gotten more polarized",
    x = "Partisan gap",
    y = NULL,
  ) +
  theme(legend.position = "none")

ggplotly(static_plot_tooltip_fancy,
  tooltip = "text"
)

Create a custom tooltip

Using Plotly

Scatterplot redux

plot_ly(
  data = gapminder_2007,
  x = ~gdpPercap,
  y = ~lifeExp,
  color = ~continent
) |>
  add_markers() |>
  layout(xaxis = list(type = "log"))

Scatterplot redux

Using Plotly

Application exercise

ae-19

Instructions

  • Go to the course GitHub org and find your ae-19 (repo name will be suffixed with your GitHub name).
  • Clone the repo in RStudio, run renv::restore() to install the required packages, open the Quarto document in the repo, and follow along and complete the exercises.
  • Render, commit, and push your edits by the AE deadline – end of the day

Other R packages for interactive charts

Or take INFO 3300/5100 to learn to do this from scratch using D3.js

Wrap-up

Recap

  • Interactivity provides additional dimensions and methods for communicating using data
  • Plotly is a powerful for creating interactive plots in R
  • Use ggplotly() to convert {ggplot2} plots to an interactive form