Code
library(ggplot2)
library(dplyr)
library(gapminder)
gap2007 <- gapminder %>% filter(year == 2007)Static graphs are ideal for print and papers. On the web, you can let readers hover, zoom, and filter. Interactivity lets you show detail on demand instead of cluttering the plot with labels.
When to use interactivity: exploratory analysis, dashboards, teaching, supplementary online material. When not to: anything that must also work on paper. Always design the static version first, an interactive chart that only works when hovered is a bad chart.
ggplotly()The fastest route to interactivity: build a normal ggplot, then wrap it in plotly::ggplotly(). Hover, zoom, and pan come for free.
library(plotly)
p <- ggplot(gap2007, aes(
x = gdpPercap, y = lifeExp,
color = continent, size = pop,
# 'text' is not a ggplot2 aesthetic; plotly picks it up for the tooltip
text = paste0(country, "\nLife exp: ", round(lifeExp, 1))
)) +
geom_point(alpha = 0.7) +
scale_x_log10() +
scale_color_viridis_d(end = 0.95) +
scale_size(range = c(1, 12), guide = "none") +
labs(x = "GDP per Capita (log scale)", y = "Life Expectancy",
color = "Continent") +
theme_minimal()
ggplotly(p, tooltip = "text")Tip: ggplotly() translates most, but not all, ggplot2 features. Facets and simple geoms work well; complex annotations and some themes get lost in translation. Check the result before publishing.
ggiraph replaces geoms with _interactive versions (geom_point_interactive(), geom_sf_interactive(), …). It stays closer to your ggplot2 styling than plotly and supports linked hovering between panels.
library(ggiraph)
gg <- ggplot(gap2007, aes(
x = gdpPercap, y = lifeExp,
tooltip = country, data_id = country # ggiraph aesthetics
)) +
geom_point_interactive(aes(color = continent), size = 3, alpha = 0.7) +
scale_x_log10() +
scale_color_viridis_d(end = 0.95) +
labs(x = "GDP per Capita (log scale)", y = "Life Expectancy") +
theme_minimal()
girafe(ggobj = gg,
options = list(opts_hover(css = "fill:red;stroke:black;")))gganimateAnimation adds time as a display dimension: the famous Hans Rosling bubble chart is exactly this.
library(gganimate)
ggplot(gapminder, aes(gdpPercap, lifeExp, size = pop, color = continent)) +
geom_point(alpha = 0.7) +
scale_x_log10() +
scale_color_viridis_d(end = 0.95) +
scale_size(range = c(2, 12), guide = "none") +
labs(title = "Year: {frame_time}", x = "GDP per Capita", y = "Life Expectancy") +
theme_minimal() +
transition_time(year) +
ease_aes("linear")
# anim_save("gapminder.gif") to exportUse animation only when time (or another ordered variable) is central to the story. A faceted static plot is often easier to compare across.
You already know mapview from the spatial examples. For more control, leaflet is the standard:
Interactive output is HTML + JavaScript. It works on websites and in HTML slides, but not in PDF or Word output. If your Quarto project renders to multiple formats, guard interactive chunks with #| eval: !expr knitr::is_html_output(). Interactive charts also carry accessibility costs: tooltips are invisible to screen readers, so never put essential information only in a tooltip.