| name | ggplot2 |
| description | Expert ggplot2 data visualization in R - grammar of graphics, geoms, themes, scales, faceting, and styling. Use when user works with ggplot2, mentions "ggplot", "geom_", creates visualizations in R, asks about plot customization, "customizar theme", "customize theme", "customizar plot", themes, "facet_wrap", "facet_grid", "faceting", "facetas", "anotações", "annotations", "annotate", "adicionar anotações", "color scale", "scales", "escala de cores", "gráfico", "plot", "visualização", or data visualization best practices. |
| version | 1.1.0 |
| allowed-tools | Read, Write, Edit, Grep, Glob |
| user-invocable | false |
ggplot2 Expert - Comprehensive Data Visualization Skill
Master data visualization in R using ggplot2's layered grammar of graphics. This skill provides expert guidance on creating effective, publication-ready visualizations with complete control over all visual elements.
The Layered Grammar of Graphics
Every ggplot2 visualization is built from five independent components:
- Layers - Data + geometric objects (geoms) + statistical transformations (stats)
- Scales - Map data values to aesthetics (color, size, position) and generate legends/axes
- Coordinate Systems - Transform data coordinates to plot positions
- Facets - Create small multiples for comparing subsets
- Themes - Control all non-data display elements
Philosophy: Build plots incrementally by composing independent components, not by selecting from fixed templates. This enables infinite flexibility while mirroring analytical thinking.
Core Workflow
1. Basic Plot Structure
ggplot(data = <DATA>, mapping = aes(<MAPPINGS>)) +
<GEOM_FUNCTION>() +
<SCALE_FUNCTIONS>() +
<COORDINATE_FUNCTION>() +
<FACET_FUNCTION>() +
<THEME_FUNCTION>()
Key Principles:
aes() maps variables to visual properties (inside geom or ggplot)
- Fixed values go outside
aes() (e.g., colour = "blue")
- Build incrementally with
+ operator
- Each layer is independent and composable
2. Layer Purpose Framework
Every layer should serve one of three purposes:
- Display raw data - Pattern detection, outlier identification
- Show statistical summaries - Model predictions, trends, aggregations
- Add metadata/context - Backgrounds, annotations, reference lines
3. Common Mistakes to Avoid
❌ Wrong: aes(colour = "blue") - Maps string "blue" as data
✅ Right: colour = "blue" outside aes() - Sets fixed color
❌ Wrong: ggplot(df, aes(x = df$variable)) - Breaks plot self-containment
✅ Right: ggplot(df, aes(x = variable)) - Self-contained reference
❌ Wrong: aes(x = log(variable)) - Complex calculation in aes
✅ Right: Use dplyr::mutate() first, then map the result
❌ Wrong: Accepting default bin widths
✅ Right: Always experiment with binwidth or bins
❌ Wrong: Mapping too many aesthetics simultaneously
✅ Right: Create series of simpler plots for clarity
Geom Selection Guide
See references/geoms-reference.md for complete documentation.
Quick Reference
Continuous Relationships:
geom_point() - Scatter plots (x-y relationships)
geom_line() - Time series (connects in x-order)
geom_path() - Connections in data order
geom_smooth() - Add trend lines with confidence bands
Distributions:
geom_histogram() - Continuous distribution via binning
geom_freqpoly() - Frequency polygon (better for comparisons)
geom_density() - Smooth density estimate
geom_boxplot() - Five-number summary with outliers
geom_violin() - Distribution shape (mirrored density)
Categorical Data:
geom_bar() - Count occurrences (stat = "count")
geom_col() - Use pre-calculated values (stat = "identity")
- Position: "stack" (default), "dodge" (side-by-side), "fill" (proportions)
Text & Annotations:
geom_text() - Add text labels
geom_label() - Text with background rectangle
annotate() - Quick single annotations without data frames
See examples/plot-examples.md for complete working examples.
Aesthetics Mapping
Universal Aesthetics (work with most geoms):
x, y - Position
colour - Border/line color
fill - Interior color (shapes 21-25, bars, areas)
alpha - Transparency (0-1)
size - Size of points/lines
shape - Point shape (0-25)
linetype - Line pattern ("solid", "dashed", "dotted", etc.)
group - Define grouping for collective geoms
Geom-Specific Aesthetics:
- Labels:
label, hjust, vjust, angle, family, fontface
- Boxplots:
lower, upper, middle, ymin, ymax
- Errorbar/ribbon:
ymin, ymax (or xmin/xmax)
Scales & Legends
See references/scales-reference.md for complete documentation.
Naming Pattern
scale_[aesthetic]_[type] - e.g., scale_colour_viridis_c()
- aesthetic: x, y, colour, fill, size, shape, alpha, linetype
- type: continuous, discrete, binned, manual, identity
Common Scale Functions
Position Scales:
scale_x_continuous(limits, breaks, labels, trans, expand)
scale_x_discrete(limits, labels, expand)
scale_x_log10()
scale_x_date(date_breaks = "1 month", date_labels = "%b %Y")
Color Scales (accessibility-first):
scale_colour_viridis_c(option = "viridis")
scale_colour_viridis_d()
scale_colour_brewer(palette = "Set1", type = "qual")
scale_fill_distiller(palette = "Blues")
scale_colour_gradient(low = "white", high = "red")
scale_colour_gradient2(low = "blue", mid = "white", high = "red", midpoint = 0)
scale_colour_gradientn(colours = c("red", "yellow", "green", "blue"))
scale_colour_manual(values = c("A" = "#E41A1C", "B" = "#377EB8"))
Important: Setting scale limits discards data outside range. Use coord_cartesian(xlim, ylim) to zoom without losing data (preserves stat calculations).
Themes & Styling
See references/themes-styling.md for complete documentation.
Built-in Themes
theme_grey()
theme_bw()
theme_minimal()
theme_classic()
theme_light()
theme_dark()
theme_void()
All themes accept: base_size, base_family, base_line_size, base_rect_size
Theme Customization
theme(
plot.title = element_text(size = 14, face = "bold"),
plot.subtitle = element_text(size = 12, colour = "grey50"),
plot.background = element_rect(fill = "white"),
plot.margin = margin(10, 10, 10, 10),
panel.background = element_rect(fill = "white"),
panel.grid.major = element_line(colour = "grey90"),
panel.grid.minor = element_blank(),
axis.title = element_text(size = 12),
axis.text = element_text(size = 10),
axis.ticks = element_line(colour = "black"),
legend.position = "right",
legend.title = element_text(face = "bold"),
legend.background = element_rect(fill = "white", colour = "black"),
strip.text = element_text(size = 11, face = "bold"),
strip.background = element_rect(fill = "grey80")
)
Element Functions:
element_text() - Customize text
element_rect() - Customize backgrounds/borders
element_line() - Customize lines
element_blank() - Remove elements entirely
Faceting
facet_wrap() - Single Variable
Use for one variable with many levels, wrapped into 2D:
facet_wrap(
~ variable,
nrow = 2, ncol = 3,
scales = "fixed",
dir = "h",
labeller = label_value
)
facet_grid() - Two Variables
Use for true 2D grid with all combinations:
facet_grid(
rows ~ cols,
scales = "fixed",
space = "fixed",
margins = FALSE,
labeller = label_value
)
When to use which:
scales = "fixed" - For cross-panel comparison (consistent axes)
scales = "free" - To highlight within-panel patterns
- Faceting > aesthetic grouping when overlap is severe
- Aesthetic grouping > faceting when comparing small differences
Coordinate Systems
coord_cartesian(xlim, ylim, expand = TRUE)
coord_fixed(ratio = 1)
coord_flip()
coord_polar()
coord_map()
Critical difference: coord_cartesian() zooms visually while scale_*_continuous(limits = ...) discards data before calculations.
Position Adjustments
position_dodge(width = 0.9)
position_stack()
position_fill()
position_jitter(width, height)
position_nudge(x, y)
Labels & Annotations
labs(
title = "Main Title",
subtitle = "Subtitle text",
caption = "Data source",
x = "X-axis label",
y = "Y-axis label",
colour = "Legend title",
fill = "Fill legend title"
)
Text Annotations:
annotate("text", x = 5, y = 10, label = "Important point",
hjust = "inward", vjust = "inward")
geom_text(aes(label = label_var), hjust = "inward", check_overlap = TRUE)
geom_label(aes(label = label_var), nudge_y = 0.5)
Reference Lines:
geom_hline(yintercept = 0, linetype = "dashed", colour = "red")
geom_vline(xintercept = 5, linetype = "dashed")
geom_abline(intercept = 0, slope = 1)
Programming with ggplot2
Tidy Evaluation (Embrace Operator)
Use {{ var }} to accept user-supplied variable names:
my_histogram <- function(data, var, bins = 30) {
ggplot(data, aes(x = {{ var }})) +
geom_histogram(bins = bins) +
theme_minimal()
}
my_histogram(mtcars, mpg, bins = 20)
Reusable Components
my_theme <- theme_minimal() +
theme(
plot.title = element_text(face = "bold"),
axis.text = element_text(size = 11)
)
ggplot(data, aes(x, y)) + geom_point() + my_theme
Plot Functions
scatter_with_smooth <- function(data, x_var, y_var, ...) {
ggplot(data, aes(x = {{ x_var }}, y = {{ y_var }})) +
geom_point(alpha = 0.5) +
geom_smooth(method = "lm", ...) +
theme_bw()
}
Combining Plots (patchwork)
library(patchwork)
p1 + p2
p1 | p2
p1 / p2
(p1 | p2) / p3
p1 + p2 +
plot_layout(ncol = 2, guides = "collect") +
plot_annotation(title = "Combined Analysis", tag_levels = "A")
Best Practices
See references/best-practices.md for comprehensive guidance.
Quick Tips
Aesthetics:
- Use colorblind-safe palettes (Viridis, ColorBrewer)
- Provide redundant encodings (size + color, or shape + color)
- Limit aesthetics per plot (3-4 max for clarity)
Annotations:
- Direct labeling > legends (reduces cognitive load)
- Use
hjust/vjust = "inward" for automatic alignment
- Set
inherit.aes = FALSE for self-contained annotations
Performance:
- Use
alpha for overplotting instead of geom_jitter()
- Consider
geom_hex() or geom_bin2d() for dense data (>10k points)
- Use
stat_summary() to aggregate before plotting
Reproducibility:
- Set explicit
binwidth/bins (never rely on defaults)
- Document all scale transformations
- Use
set.seed() before jittering
- Export with
ggsave() using vector formats (PDF/SVG) for publication
Quick Start Examples
ggplot(mpg, aes(displ, hwy)) +
geom_point(aes(colour = class)) +
geom_smooth(method = "lm", se = TRUE) +
scale_colour_viridis_d() +
labs(title = "Engine Size vs Highway MPG",
x = "Displacement (L)", y = "Highway MPG") +
theme_minimal()
ggplot(mpg, aes(hwy)) +
geom_histogram(binwidth = 2, fill = "steelblue", colour = "white") +
facet_wrap(~ class, scales = "free_y") +
theme_bw()
ggplot(mpg, aes(class, hwy, fill = class)) +
geom_boxplot(show.legend = FALSE) +
scale_fill_brewer(palette = "Set2") +
coord_flip() +
theme_minimal() +
theme(panel.grid.major.y = element_blank())
See examples/plot-examples.md for comprehensive working examples.
See templates/plot-templates.md for reusable templates.
Workflow Guidance
When user asks about ggplot2 visualizations:
- Understand the goal: What pattern/comparison/relationship to show?
- Select appropriate geom: Match data type and purpose
- Map aesthetics: Which variables map to which visual properties?
- Choose scales: Appropriate for data type (continuous/discrete/date)
- Apply theme: Publication-ready styling
- Add context: Labels, annotations, reference lines
- Optimize: Adjust transparency, position, faceting for clarity
Always provide complete, runnable code examples with proper formatting and best practices applied.
Additional Resources
Core References
Examples & Gallery