ggplot2 vs plotly: When to Use Each in R
The ggplot2 vs plotly decision is one of the most common and consequential choices R users face when building data visualizations. Both packages are powerful, but they serve different purposes and excel in different scenarios. This ggplot2 vs plotly guide helps you pick the right tool for your project.
The short answer
Use ggplot2 for static publications. Use plotly for interactive web applications.
This is the simplest way to think about it, but the reality has more nuance. Both packages can create both static and interactive plots, but each has a primary strength that makes it the better choice for specific use cases.
ggplot2 has been the gold standard for static visualizations in R since 2005. plotly, which came to R from JavaScript, has become the go-to for interactive web-based visualizations. Understanding when to use each will save you time and produce better results.
What ggplot2 does well
ggplot2 follows the grammar of graphics—a layered approach where you build charts piece by piece. This declarative style makes it incredibly intuitive once you learn the syntax:
library(ggplot2)
ggplot(mpg, aes(displ, hwy, color = class)) +
geom_point() +
labs(title = "Fuel Efficiency by Engine Displacement",
subtitle = "Each point is a car model",
x = "Engine displacement (L)",
y = "Highway miles per gallon") +
theme_minimal()
When to choose ggplot2
- Academic papers and reports, Static images in PDF or PNG format
- Publication-quality graphics, Fine-grained control over every visual element
- Complex, multi-layered visualizations, Facets, annotations, custom themes
- When you need the fastest rendering, ggplot2 is significantly faster for large datasets
- Learning the grammar of graphics, The conceptual framework transfers to other tools
The strength of ggplot2 is its extensibility. Packages like gganimate for animations, patchwork for composing plots, and ggthemes for pre-built styles build on top of ggplot2 to handle almost any visualization need.
ggplot2 limitations
The main limitation is interactivity. While you can make interactive ggplot2 visualizations using ggiraph or plotly::ggplotly(), the native output is static. This is perfect for print but problematic for web applications where users need to hover, zoom, and pan.
What plotly does well
plotly creates interactive HTML visualizations that work in web browsers, R Markdown documents, and Shiny applications. The same syntax that creates web graphics also works in R:
library(plotly)
plot_ly(mpg, x = ~displ, y = ~hwy, color = ~class,
type = "scatter", mode = "markers") %>%
layout(title = "Fuel Efficiency by Engine Displacement",
xaxis = list(title = "Engine displacement (L)"),
yaxis = list(title = "Highway miles per gallon"))
When to choose plotly
- Web applications, Shiny apps, dashboards, interactive reports
- Exploratory data analysis, Hover tooltips save clicks
- Sharing visualizations online, Anyone can interact without R
- 3D visualizations, plotly handles 3D scatter and surface plots natively
- When stakeholders need to explore data, Interactive zooming and panning
The interactivity is the killer feature. When you need users to hover over points to see exact values, filter data by clicking legend items, or zoom into dense regions, plotly delivers this out of the box.
plotly limitations
Performance can be an issue with very large datasets. Each interactive element adds JavaScript overhead, and rendering thousands of points in the browser takes time. Customizing every visual element is also more complex than in ggplot2, and the trade-off for interactivity is sometimes less precise control.
Converting between them
Here is the secret most R users do not know: you do not have to choose one. The ggplotly() function converts ggplot2 visualizations to interactive plotly with a single function call:
library(plotly)
p <- ggplot(mpg, aes(displ, hwy, color = class)) +
geom_point() +
theme_minimal()
ggplotly(p)
This gives you the best of both worlds—use ggplot2’s intuitive grammar to build the visualization, then convert to plotly for interactivity when needed. The trade-off is that not all ggplot2 features transfer perfectly, so test your converted plots carefully.
Performance comparison
For static plots with large datasets, ggplot2 is noticeably faster. A 2025 benchmark from Jumping Rivers found that plotly’s plot_ly() can be slower than ggplotly(), which itself adds conversion overhead. If rendering speed matters for your pipeline, stick with pure ggplot2 for static outputs.
For interactive plots, the difference is less noticeable to users. Both render quickly for datasets under 10,000 points. Beyond that, consider downsampling or using interactive widgets that load data on demand.
What about the grammar?
If you learn ggplot2’s grammar of graphics, you are building a transferable skill. The concepts of mapping data to visual aesthetics, layering geoms, and specifying scales appear in other tools. plotly has its own syntax that is specific to the plotly ecosystem.
This is worth considering if you work across multiple languages. The Python plotly library uses nearly identical syntax to R plotly. ggplot2 concepts also transfer to Python’s plotnine and Tableau’s visualization grammar.
Decision framework
Use this quick reference to guide your choice:
| Scenario | Recommendation |
|---|---|
| PDF report or academic paper | ggplot2 |
| Shiny dashboard | plotly |
| Quick EDA in RStudio | Either works |
| Publication with precise styling | ggplot2 |
| Sharing with non-R users | plotly |
| Animated visualizations | ggplot2 + gganimate |
| 3D scatter plots | plotly |
| Thousands of points | ggplot2 |
| Interactive tables + charts | plotly |
Code complexity and learning curve
ggplot2’s grammar of graphics has a steeper initial learning curve than plotly’s function-based API. ggplot(data, aes(x, y)) + geom_point() requires understanding layers and aesthetics before you can produce the first plot. plotly’s plot_ly(data, x = ~x, y = ~y, type = "scatter", mode = "markers") is more immediately readable to users familiar with other charting APIs.
Once the mental model clicks, ggplot2 scales better to complex charts. Adding a color variable, facets, and a fitted line is three + operations: + aes(color = group) + facet_wrap(~category) + geom_smooth(). The equivalent in plotly requires more code for each of these customizations.
ggplotly(p) from the plotly package converts most ggplot2 objects to interactive plotly charts with one line. This makes ggplot2 the clear starting point: build the chart in ggplot2, then convert if interactivity is needed. The conversion is not perfect, custom themes and some geoms render differently, but it handles 90% of charts correctly and removes the need to learn plotly’s API for most use cases.
Output and reproducibility
ggplot2 output is deterministic: the same code produces the same chart every time. Saving a ggplot to SVG or PDF via ggsave() produces a vector graphic with precise positioning. plotly renders in a browser via JavaScript, which means the final appearance depends on the browser and screen resolution. For reproducible paper figures or automated report pipelines, ggplot2’s static output is more reliable.
Package maintenance and stability
ggplot2 is one of the most stable R packages: the API has been backward-compatible since version 2.0 (2015), and breaking changes require a deprecation cycle of at least one release cycle. plotly for R is a wrapper around the plotly.js JavaScript library, which means it inherits updates (and occasional API changes) from the JavaScript side. Both packages are well-maintained in 2026 with active GitHub communities.
Decision guide
Use ggplot2 when producing static publication-quality plots, when you need the full range of statistical geoms, or when rendering in PDF or Word. Use plotly when your output is an HTML document or Shiny app and interactivity, tooltips, zoom, pan, adds genuine value for your audience. ggplotly() gives a practical middle path: design in ggplot2, convert to plotly for deployment, and accept some loss of fine-grained control over the interactive output.
See also
r-ggplot2-extensions, Extend ggplot2 with patchwork, ggrepel, and gganimater-plotly-guide, Interactive visualizations with plotly in Rdata-viz-best-practices-r, Principles for effective data visualization