Interactive Visualization; Animated Plots
April 21, 2025
plotly::ggplotly()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.
plotly::ggplotly().ggplotly() interacts with ggplot objects to make those figures interactive.cces <- read_csv(url("https://bcdanl.github.io/data/cces.csv"))
cces <- cces |>
mutate(party = recode(dem, `1` = "Democrat", `0` = "Republican"))recode() to create a new variable corresponding to other factor variable.
les is a score for legislative effectiveness.
ggiraphggiraph is a R package that allows us to create dynamic ggplot.
shiny applications.tooltip: tooltips to be displayed when mouse is over elements.data_id: id to be associated with elements (necessary for hover and click actions)onclick: JavaScript to be executed when elements are clicked.The things we need to know to create a ggiraph interactive graphic:
geom_point, use geom_point_interactive.geom_sf, use geom_sf_interactive.tooltip, data_id and/or onclick, to create interactive elements.girafe with the ggplot object so that the graphic is translated as a web interactive graphics.gganimatemtcars.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.transition_states()transition_states() is intended to use primarily with categorical variables.
transition_length and state_length arguments.seniority against all_pass.
seniority is about how long a member has been in Congress.all_pass is about how many bills a member passedp <- 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"))
penter_*()/exit_*()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.shadow_*()shadow_*() allows for retaining 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 +
geom_text(aes(x = min(gdpPercap),
y = min(lifeExp),
label = as.factor(year)) ,
hjust=-2, vjust = -0.2, alpha = 0.2,
color = "gray", size = 20) +
transition_states(as.factor(year), state_length = 0)state_length allows us to control for how long will pause before changing to the new state.view_follow()view_follow() function.gapminder |>
filter(country == "United States") |>
ggplot(aes(x = year, y = pop)) +
geom_point() + geom_line() +
geom_text(aes(x = min(year), y = min(pop),
label = as.factor(year)) ,
hjust=-2, vjust = -0.2, alpha = 0.5,
color = "gray", size = 20) +
theme_minimal() +
transition_reveal(year) +
view_follow()Frames and duration are the key for a good quality of animation.
We can adjust several key elements of our animations, such as:
width and height of the animation to create an animation.fps): this will make us the animation see fluently.
fps parameter is recommended to be higher than 12.gif, you can also create a video too (e.g., mp4).gdpPercap for each year:p <- gapminder_sum |>
ggplot() +
geom_col(aes(x = ranking, y = gdpPercap, fill = country)) +
geom_text(aes(x = ranking, y = gdpPercap, label = round(gdpPercap, 0)),
hjust=-0.1) +
geom_text(aes(x = ranking, y = 0 ,
label = country), hjust=1.1) +
geom_text(aes(x = 15,
y = max(gdpPercap),
label = as.factor(year)),
vjust = 0.2, alpha = 0.5, color = "gray", size = 20) +
coord_flip(clip = "off", expand = FALSE) +
scale_x_reverse() +
theme_minimal() +
theme(
panel.grid = element_blank(),
legend.position = "none",
axis.ticks.y = element_blank(),
axis.title.y = element_blank(),
axis.text.y = element_blank(),
plot.margin = margin(1, 4, 1, 3, "cm")
)anim <- p +
transition_states(year, state_length = 0, transition_length = 2) +
enter_fade() +
exit_fade() +
ease_aes('quadratic-in-out')
p_anim <- animate(anim,
width = 700, height = 432,
fps = 25, duration = 15,
rewind = FALSE)
p_animrewind: Controls what happens at the end of the sequence.
FALSE: Jumps back to the first frame and repeats from the beginningTRUE: After reaching the last frame it’ll play the animation in reverse back to the start