Interactive Visualizations with plotly

· 4 min read · Updated March 12, 2026 · intermediate
r data-viz plotly interactive

Interactive visualizations let your audience explore data rather than just view static images. The plotly package provides R programmers with a powerful way to build interactive charts that work in HTML documents, Shiny apps, and standalone HTML files.

Unlike static ggplot2 images, plotly charts respond to user input. Viewers can hover to see exact values, click legend items to filter categories, zoom into regions of interest, and pan around large datasets. This makes plotly ideal for exploratory data analysis and presenting findings to stakeholders who need to dig into the numbers themselves.

Installing plotly

Install plotly from CRAN or get the development version from GitHub:

# From CRAN
install.packages("plotly")

# Or from GitHub for latest features
# remotes::install_github("plotly/plotly.R")

Load it alongside tidyverse if you prefer:

library(plotly)
library(tidyverse)

Converting ggplot2 to plotly

If you already know ggplot2, plotly makes it easy to convert your existing plots to interactive versions without rewriting everything. The ggplotly() function takes a ggplot object and returns an interactive plotly object:

# Create a ggplot first
p <- ggplot(mpg, aes(displ, hwy, color = class)) +
  geom_point() +
  labs(title = "Fuel Efficiency by Engine Displacement",
       x = "Engine Displacement (L)",
       y = "Highway MPG") +
  theme_minimal()

# Convert to interactive plotly
ggplotly(p)

This approach lets you build visualizations with familiar ggplot2 syntax, then add interactivity afterward. Hover over points to see values, click legend items to toggle categories, and drag to zoom. The conversion preserves most aesthetics including colors, shapes, and transparency.

Basic Interactive Charts

Plotly also works directly with its own syntax. Here is how to create common chart types:

Scatter Plot

plot_ly(data = mtcars, x = ~wt, y = ~mpg, 
        color = ~factor(cyl), 
        type = "scatter", mode = "markers") %>%
  layout(title = "Car Weight vs MPG",
         xaxis = list(title = "Weight (1000 lbs)"),
         yaxis = list(title = "Miles per Gallon"))

Bar Chart

plot_ly(data = count(mpg, class), x = ~class, y = ~n, 
        type = "bar", 
        marker = list(color = "steelblue")) %>%
  layout(title = "Cars per Class",
         yaxis = list(title = "Count"))

Histogram

plot_ly(data = iris, x = ~Sepal.Length, type = "histogram") %>%
  layout(title = "Sepal Length Distribution")

3D Visualizations

Plotly supports 3D scatter plots and surfaces, which are useful for exploring multivariate data that would be hard to see in two dimensions:

plot_ly(data = iris, x = ~Sepal.Length, y = ~Sepal.Width, 
        z = ~Petal.Length, color = ~Species) %>%
  add_markers() %>%
  layout(scene = list(xaxis = title("Sepal Length"),
                      yaxis = title("Sepal Width"),
                      zaxis = title("Petal Length")))

3D plots can be rotated by clicking and dragging, letting you find angles that reveal patterns in your data. Use them sparingly though - they can be harder to interpret than 2D views.

Creating Subplots

Combine multiple plots into one figure using subplot() when you need to compare different views side by side:

p1 <- plot_ly(data = mtcars, x = ~wt, y = ~mpg, type = "scatter", mode = "markers")
p2 <- plot_ly(data = mtcars, x = ~wt, y = ~disp, type = "scatter", mode = "markers")
p3 <- plot_ly(data = mtcars, x = ~wt, y = ~hp, type = "scatter", mode = "markers")

subplot(p1, p2, p3, nrows = 1, shareX = TRUE, titleX = FALSE)

Set shareX = TRUE to synchronize zooming across all subplots, which is helpful when comparing variables against the same scale.

Animations

Create animated visualizations that cycle through categories to show how values change over time or across groups:

plot_ly(data = mtcars, x = ~wt, y = ~mpg, 
        frame = ~factor(cyl),
        type = "scatter", mode = "markers") %>%
  animation_opts(frame = 1000, transition = 800)

The frame argument specifies which variable to animate through. Use this to build narratives around change over time or categorical transitions.

Customizing Layout

The layout() function controls titles, axes, legends, and styling:

plot_ly(data = mtcars, x = ~wt, y = ~mpg, type = "scatter", mode = "markers") %>%
  layout(
    title = list(text = "Weight vs MPG", font = list(size = 20)),
    xaxis = list(title = "Weight", showgrid = FALSE),
    yaxis = list(title = "MPG", showgrid = TRUE),
    plot_bgcolor = "#f0f0f0",
    paper_bgcolor = "white"
  )

Sharing Your Visualizations

Interactive plotly charts render as HTML widgets. Save them as standalone HTML files:

# Save to HTML file
htmlwidgets::saveWidget(plot_ly(data = mtcars, x = ~wt, y = ~mpg, 
                                type = "scatter", mode = "markers"),
                        "my-plot.html")

Or embed them in R Markdown documents or Shiny apps for web-based presentations.

See Also