March 24, 2022

Interactive visualization

R packages

# install.packages("gganimate") 
# install.packages("plotly") 
# install.packages("gifski")   # for PCs.
# install.packages("transformr")   # for manipulating polygons and paths
# install.packages("magick")  # for animation rendering
# install.packages("htmltools")  # for html rendering

library(tidyverse)
library(plotly)
library(gganimate)
library(gifski)
library(transformr)
library(magick)
library(htmltools)
theme_set(theme_bw())

gganimate

  • Consider the relationship between cyl and mpg from mtcars data, which is provided by the ggplot2 package.
data(mtcars)

p <- ggplot(data = mtcars,
       mapping = aes(x = factor(cyl), y = mpg)) +
  geom_boxplot()

p

gganimate

gganimate

  • Let us consider how the relationship between cyl and mpg vary by gear.
p + facet_wrap(~gear)

gganimate

gganimate

  • gganimate turn our ggplot visualizations into moving images.

    • gganimate takes a ggplot figure and creates many different versions of it by changing a single parameter in the data.
my_anim <- p + 
  transition_states(gear)

my_anim

gganimate

gganimate

  • transition_states() is intended to use primarily with categorical variables.

    • You can control the link for each transition and the amount of time spent on each of the states using the transition_length and state_length arguments.
my_anim2 <- p + 
  transition_states(gear,
    transition_length = 3,  # relative length
    state_length = 2)  # relative length

my_anim2

gganimate

Cooperative Congressional Election Survey

  • Cooperative Congressional Election Survey (CCES) is a 50,000+ person national stratified sample survey.

  • We can use recode() to create a new variable corresponding to other factor variable.

  • Here we summarize the number of Democrats and Republicans in a series of years.

  • There are usually 435 seats in total in the House of Representatives.

cces <- read_csv(url("https://bcdanl.github.io/data/cces.csv"))
cces <- cces %>% 
  mutate(party = recode(dem,`1`="Democrat",`0`="Republican"))

cong_dat <- cces %>% 
  group_by(year, party) %>%
  summarise( seats =n())

Cooperative Congressional Election Survey

p <- ggplot(cong_dat, 
            aes(x = year, y= seats, 
                fill = party)) +
  geom_bar(stat="identity") +
  geom_hline(yintercept = 217) +  # threshold for having a majority of seats in the house.
  scale_fill_manual(values=c("blue","red"))

p

Cooperative Congressional Election Survey

gganimate

  • transition_time() is intended for time-series data like hours, minutes, days, weeks months, years, etc.
anim2 <- p + transition_time(year)

anim2

gganimate

Cooperative Congressional Election Survey

  • Let’s consider a scatter plot of seniority against all_pass.

    • Variable seniority is about how long a member has been in Congress.

    • Variable all_pass is about how many bills a member passed

Cooperative Congressional Election Survey

p <- ggplot() + geom_jitter(data = filter(cces, 
                            congress==115 & party=="Democrat"),
              aes(x = seniority, y = all_pass,
                  color = party) ) +
  geom_jitter(data = filter(cces, 
                            congress==115 & party=="Republican"),
              aes(x = seniority, y = all_pass,
                  color = party) ) +
  geom_smooth(data = filter(cces, 
                            congress==115 & party=="Democrat"),
              aes(x = seniority, y = all_pass,
                  color = party) ) +
  geom_smooth(data = filter(cces, 
                            congress==115 & party=="Republican"),
              aes(x = seniority, y = all_pass,
                  color = party) ) +
  scale_color_manual(values=c("blue","red"))

p

Cooperative Congressional Election Survey

gganimate

  • transition_layers() allow for building up a plot layer by layer with an animation.
anim2 <- p + transition_layers()

anim2

gganimate

  • enter_*() and exit_*() allow for controlling the entering and exiting in gganimate.

    • *_fade() will set the alpha value to zero making the elements fade in/out during the transition.
anim <- ggplot(mtcars, aes(factor(cyl), mpg)) +
  geom_boxplot() +
  transition_states(factor(cyl))

# Fade-in, fade-out
anim1 <- anim +
  enter_fade() +
  exit_fade()

anim1

gganimate

  • shadow_*() allows you to retain previous or preview future frames of the animation.

  • shadow_wake() shows preceding frames with gradual falloff.

    • alpha is for transparency modification of the wake.
    • wrap should the shadow wrap around, so that the first frame will get shadows from the end of the animation.
  • There are also shadow_mark(), shadow_null(), and shadow_trail().

p <- ggplot(cong_dat,
                aes(x = year, y = seats, fill = party)) +
  geom_bar(stat = "identity") +
  geom_hline(yintercept = 217) +
  scale_fill_manual(values = c("blue","red"))


anim3 <- p + transition_time(year) +
  shadow_wake(wake_length = 1,
              alpha = TRUE,
              wrap = TRUE)

anim3

gganimate

p <- ggplot(cong_dat,
                aes(x = year, y = seats, fill = party)) +
  geom_bar(stat = "identity") +
  geom_hline(yintercept = 217) +
  scale_fill_manual(values = c("blue","red"))


anim3 <- p + transition_time(year) +
  shadow_wake(wake_length = 1,
              alpha = FALSE,
              wrap = FALSE)

anim3

gganimate

  • anim_save() saves saves the animation object as a *.gif file.
anim_save("test.gif", animation = anim3)

plotly

  • plotly is an alternative to ggplot with a relatively easy to learn syntax for generating many of the same kinds of plots.

  • plotly is mainly for the interactive figures of visualization.

    • We will focus only on plotly::ggplotly().

    • ggplotly() interacts with ggplot figures to make those figures interactive.

# Make some noisily increasing data
dat <- data.frame(cond = rep(c("A", "B"), each = 10),
                  xvar = 1:20 + rnorm(20, sd=3),
                  yvar = 1:20 + rnorm(20, sd=3))

p <- ggplot(dat, aes(x = xvar, y = yvar)) +
  geom_point(shape=1)      # Use hollow circles
fig <- ggplotly(p)
fig

plotly

  • Like gganimate, plotly can animate ggplot figures by creating frames of the animation based on some value in your data.

  • Consider the static relationship between seniority and legislative effectiveness using CCES data.

    • Variable les is a score for legislative effectiveness.
    • It measures how productive members of Congress are at making laws.
p <- ggplot(cces, aes(x = seniority, y = les,
                      color = party))+
  geom_point()+
  scale_color_manual(values=c("blue","red")) +
  labs(x = "Seniority", y = "Leg. Effectiveness")

p

plotly

  • Now consider the dynamic relationship between seniority and legislative effectiveness using CCES data.

    • frame parameter in the aes() function animates the figure.
p <- ggplot(cces, aes(x = seniority, y = les,
                      color = party,
                      frame = year) ) + #this animates the figure
  geom_point()+
  scale_color_manual(values = c("blue","red")) +
  labs(x = "Seniority", y = "Leg. Effectiveness")

p1 <- ggplotly(p)
p1

plotly

  • Now consider the dynamic relationship between seniority and legislative effectiveness using CCES data.

    • ids parameter in the aes()function smooths out the figure by adding the object constancy to the figure.

      • ids causes points to move from their points in the previous frame rather than being redrawn from scratch every single time.
p <- ggplot(cces, aes(x = seniority, y = les,
                      color = party,
                      frame = year,
                      ids = thomas_name) ) + # this adds the object constancy
  geom_point()+
  scale_color_manual(values = c("blue","red")) +
  labs(x = "Seniority", y = "Leg. Effectiveness")

p1 <- ggplotly(p)
p1

plotly

    • htmlwidgets::saveWidget() saves the ggplotly object as an *.html file.
htmlwidgets::saveWidget(p1, "fig.html")