ggplot2 Cheat Sheet
Reference for ggplot2's grammar of graphics, common geoms, faceting, and theming used to build layered statistical visualizations in R.
Grammar of Graphics Basics
Map data to aesthetics and add a geometry layer.
library(ggplot2)ggplot(data = mpg, aes(x = displ, y = hwy, color = class)) + geom_point(size = 2, alpha = 0.7) + labs(title = "Engine Size vs Highway MPG", x = "Displacement (L)", y = "Highway MPG") + theme_minimal()
Common Geoms
The most frequently used chart types.
# Bar chartggplot(mpg, aes(x = class)) + geom_bar()# Line chartggplot(economics, aes(x = date, y = unemploy)) + geom_line()# Boxplotggplot(mpg, aes(x = class, y = hwy)) + geom_boxplot()# Histogramggplot(mpg, aes(x = hwy)) + geom_histogram(binwidth = 2)# Smoothed trend lineggplot(mpg, aes(x = displ, y = hwy)) + geom_point() + geom_smooth(method = "lm", se = TRUE)
Faceting & Themes
Build small multiples and control non-data plot elements.
ggplot(mpg, aes(x = displ, y = hwy)) + geom_point() + facet_wrap(~ class, ncol = 3) + # small multiples by category theme_bw() + theme(legend.position = "bottom")ggsave("plot.png", width = 8, height = 5, dpi = 300)
Key Concepts
The layered vocabulary behind every ggplot2 chart.
- ggplot()- Initializes a plot object with a dataset and default aesthetic mappings
- aes()- Maps data columns to visual properties (x, y, color, fill, size, shape)
- geom_*- Geometric layer that determines the chart type: geom_point, geom_bar, geom_line, etc.
- facet_wrap/facet_grid- Splits the plot into a grid of subplots (small multiples) by a categorical variable
- scale_*- Controls axis/legend mapping, e.g. scale_color_manual() for custom colors
- theme()- Adjusts non-data plot elements: fonts, gridlines, legend position, background
- stat vs geom- Every geom has a default stat (e.g. geom_bar uses stat_count) that transforms data before drawing
Custom Scales & Color Palettes
Control color mapping, manual palettes, and axis transforms.
# Continuous color scale from the viridis family (colorblind-safe)ggplot(mpg, aes(displ, hwy, color = cty)) + geom_point() + scale_color_viridis_c(option = "plasma")# Manual discrete palette with a named vectorggplot(mpg, aes(class, fill = drv)) + geom_bar() + scale_fill_manual(values = c("4" = "#1b9e77", "f" = "#d95f02", "r" = "#7570b3"))# Log-scaled axis with formatted labelsggplot(diamonds, aes(carat, price)) + geom_point(alpha = 0.1) + scale_x_log10() + scale_y_continuous(labels = scales::dollar)
Building & Setting a Custom Theme
Compose a reusable theme object and apply it session-wide.
library(ggplot2)my_theme <- theme_minimal(base_size = 13) + theme( plot.title = element_text(face = "bold", size = 16), panel.grid.minor = element_blank(), legend.position = "top", strip.background = element_rect(fill = "grey20"), strip.text = element_text(color = "white") )theme_set(my_theme) # applies to every plot for the rest of the sessionggplot(mpg, aes(displ, hwy)) + geom_point() + labs(title = "Custom Theme")
Coordinate Systems & Annotations
Reshape the plotting space and add fixed, non-data reference elements.
# Flip axes without swapping the aes mappingsggplot(mpg, aes(x = class, y = hwy)) + geom_boxplot() + coord_flip()# Polar coordinates turn a stacked bar into a pie/donutggplot(mpg, aes(x = "", fill = class)) + geom_bar(width = 1) + coord_polar(theta = "y")# Free-text annotation at fixed data coordinates (not tied to a geom)ggplot(mpg, aes(displ, hwy)) + geom_point() + annotate("text", x = 6, y = 40, label = "outlier region", color = "red") + annotate("rect", xmin = 5, xmax = 7, ymin = 35, ymax = 45, alpha = 0.1)
stat_summary(), Ribbons & Multi-Plot Composition
Summarize on the fly, draw confidence bands, and combine plots with patchwork.
# Summarize on the fly without pre-aggregating the data frameggplot(mpg, aes(class, hwy)) + geom_jitter(width = 0.1, alpha = 0.4) + stat_summary(fun = mean, geom = "point", color = "red", size = 3) + stat_summary(fun.data = mean_se, geom = "errorbar", width = 0.2)# Confidence-style bands with geom_ribbonggplot(economics, aes(date, unemploy)) + geom_ribbon(aes(ymin = unemploy * 0.95, ymax = unemploy * 1.05), fill = "grey80") + geom_line()# Compose multiple ggplots into one figurelibrary(patchwork)p1 <- ggplot(mpg, aes(displ, hwy)) + geom_point()p2 <- ggplot(mpg, aes(class)) + geom_bar()p1 + p2 + plot_layout(ncol = 2)
Advanced ggplot2 Concepts
Deeper machinery and ecosystem packages beyond the core grammar.
- Position adjustments- position_dodge(), position_stack(), and position_jitter() control how overlapping geoms are arranged
- guides()- Fine-grained legend control, e.g. guides(color = guide_legend(nrow = 2))
- ggplot_build()- Inspects the computed data/render tree behind a plot object, useful for debugging stats
- ggproto- The OOP system ggplot2 extensions use to define new Geoms/Stats/Positions
- Extension ecosystem- patchwork (composition), gganimate (animation), ggrepel (non-overlapping labels), plotly::ggplotly() (interactivity)
- Discrete vs continuous defaults- ggplot2 infers scale type from the aesthetic's data type; override with scale_*_continuous()/scale_*_discrete()
- Layer-specific data/aes- Each geom_*() layer can override the plot-level data/aes, e.g. geom_point(data = subset_df)
Build ggplot2 charts by adding layers incrementally with + and re-running after each addition - since the grammar of graphics is layer-based, this makes it easy to see exactly which layer introduced an unexpected change.