Ggplot2

by jsperger

skill

Use when working with R ggplot2 package, especially ggplot2 4.0+ features. Covers S7 migration (@ property access), theme defaults with ink/paper/accent, element_geom(), from_theme(), theme shortcuts (theme_sub_*), palette themes, labels with dictionary/attributes, discrete scale improvements (palette, continuous.limits, minor_breaks, sec.axis), position aesthetics (nudge_x/nudge_y, order), facet_wrap dir/space/layout, boxplot/violin/label styling, stat_manual(), stat_connect(), coord reversal.

Skill Details

Repository Files

1 file in this skill directory


name: ggplot2 description: Use when working with R ggplot2 package, especially ggplot2 4.0+ features. Covers S7 migration (@ property access), theme defaults with ink/paper/accent, element_geom(), from_theme(), theme shortcuts (theme_sub_*), palette themes, labels with dictionary/attributes, discrete scale improvements (palette, continuous.limits, minor_breaks, sec.axis), position aesthetics (nudge_x/nudge_y, order), facet_wrap dir/space/layout, boxplot/violin/label styling, stat_manual(), stat_connect(), coord reversal.

ggplot2 Reference

ggplot2 is an R package for producing visualizations using a grammar of graphics. You compose plots from data, mappings, layers, scales, facets, coordinates, and themes.

Core Components

Data and Mapping

ggplot(data = mpg, mapping = aes(x = cty, y = hwy))
  • Data: Tidy data frame (rows = observations, columns = variables)
  • Mapping: aes() links data columns to visual properties (x, y, colour, size, etc.)

Layers

Layers display data using geometry, statistical transformation, and position adjustment:

ggplot(mpg, aes(cty, hwy)) +
  geom_point() +
  geom_smooth(formula = y ~ x, method = "lm")

Scales

Control how data maps to visual properties and create legends/axes:

ggplot(mpg, aes(cty, hwy, colour = class)) +
  geom_point() +
  scale_colour_viridis_d()

Facets

Split data into panels by variables:

ggplot(mpg, aes(cty, hwy)) +
  geom_point() +
  facet_grid(year ~ drv)

Coordinates

Interpret position aesthetics (Cartesian, polar, map projections):

ggplot(mpg, aes(cty, hwy)) +
  geom_point() +
  coord_fixed()

Theme

Control non-data visual elements:

ggplot(mpg, aes(cty, hwy, colour = class)) +
  geom_point() +
  theme_minimal() +
  theme(legend.position = "top")

ggplot2 4.0 Features

ggplot2 4.0.0 (September 2025) introduced S7 classes and major new features.

S7 Migration

Access properties with @ instead of $:

# ggplot2 4.0+
ggplot()@data

# Deprecated (still works temporarily)
ggplot()$data

Stricter type validation:

element_text(hjust = "foo")
#> Error: @hjust must be <NULL>, <integer>, or <double>, not <character>

Theme-Based Layer Defaults

Ink, Paper, and Accent

Built-in themes accept ink (foreground), paper (background), accent (highlight):

ggplot(mpg, aes(displ, hwy)) +
  geom_point() +
  geom_smooth(method = "lm", formula = y ~ x) +
  theme_gray(paper = "cornsilk", ink = "navy", accent = "tomato")

element_geom() and from_theme()

Set layer defaults via theme(geom):

ggplot(mpg, aes(class, displ)) +
  geom_boxplot(aes(colour = from_theme(accent))) +
  theme(geom = element_geom(
    accent = "tomato",
    paper = "cornsilk",
    bordertype = "dashed",
    borderwidth = 0.2,
    linewidth = 2,
    linetype = "solid"
  ))

Theme Palettes

Set default palettes in themes:

theme(
  palette.colour.continuous = c("chartreuse", "forestgreen"),
  palette.shape.discrete = c("triangle", "triangle open")
)

Theme Shortcuts

New theme_sub_*() functions reduce verbosity:

Shortcut Prefix replaced
theme_sub_axis() axis.*
theme_sub_axis_x() axis.*.x
theme_sub_axis_bottom() axis.*.x.bottom
theme_sub_legend() legend.*
theme_sub_panel() panel.*
theme_sub_plot() plot.*
theme_sub_strip() strip.*
# Concise
theme_sub_axis_x(
  ticks = element_line(colour = "red"),
  ticks.length = unit(5, "mm")
) +
theme_sub_panel(
  widths = unit(5, "cm"),
  spacing.x = unit(5, "mm")
)

Margin Helpers

margin_auto(1)           # all sides = 1
margin_auto(1, 2)        # t/b=1, l/r=2
margin_auto(1, 2, 3)     # t=1, l/r=2, b=3
margin_part(r = 20)      # partial (NA inherits)

Panel Sizes

theme_sub_panel(widths = unit(c(2, 3, 4), "cm"))  # per-panel
theme_sub_panel(widths = unit(9, "cm"))           # total area

Labels

Label Attributes

Variables with "label" attribute auto-populate axis labels:

attr(df$bill_dep, "label") <- "Bill depth (mm)"
ggplot(df, aes(bill_dep, bill_len)) + geom_point()

Dictionary Labels

dict <- c(species = "Species", bill_dep = "Bill depth (mm)")
ggplot(penguins, aes(bill_dep, bill_len, colour = species)) +
  geom_point() +
  labs(dictionary = dict)

Function Labels

scale_colour_discrete(name = toupper)
guides(x = guide_axis(title = tools::toTitleCase))
labs(y = \(x) paste0(x, " variable"))

Label hierarchy (lowest to highest): aes() < labs(dictionary) < column attribute < labs() < scale_*(name) < guide_*(title)

Named Breaks

scale_colour_discrete(breaks = c(
  "Pygoscelis adeliae" = "Adelie",
  "Pygoscelis papua" = "Gentoo"
))

Discrete Scale Improvements

# Palette for spacing
scale_x_discrete(palette = scales::pal_manual(c(1:3, 5:7)))

# Consistent limits across facets
scale_x_discrete(continuous.limits = c(1, 5))

# Minor breaks
scale_x_discrete(
  minor_breaks = scales::breaks_width(1, offset = 0.5),
  guide = guide_axis(minor.ticks = TRUE)
)

# Secondary axis
scale_x_discrete(sec.axis = dup_axis(
  name = "Counts",
  breaks = seq_len(7),
  labels = paste0("n = ", table(mpg$class))
))

Position Aesthetics

Nudge Aesthetics

geom_text(aes(nudge_x = sign(value) * 3, label = value))

Dodge Order

ggplot(data, aes(x, y, fill = group)) +
  geom_boxplot(position = position_dodge(preserve = "single")) +
  aes(order = group)

Facets

Wrapping Directions

8 direction options for facet_wrap(dir):

dir Start Fill
"lt" top-left left-to-right
"tl" top-left top-to-bottom
"lb" bottom-left left-to-right
"bl" bottom-left bottom-to-top
"rt" top-right right-to-left
"tr" top-right top-to-bottom
"rb" bottom-right right-to-left
"br" bottom-right bottom-to-top

Free Space

facet_wrap(~ island, scales = "free_x", space = "free_x")

Layer Layout

geom_point(colour = "grey", layout = "fixed_rows")  # repeat in rows
geom_point(layout = NULL)                            # use facet vars
annotate("text", label = "X", layout = 6)            # specific panel

Options: NULL, "fixed", <integer>, "fixed_cols", "fixed_rows"

Styling

Boxplot Parts

geom_boxplot(
  whisker.linetype = "dashed",
  box.colour = "black",
  median.linewidth = 2,
  staplewidth = 0.5,
  staple.colour = "grey50"
)

Violin Quantiles

geom_violin(
  quantiles = c(0.1, 0.9),
  quantile.linetype = 1,
  quantile.colour = "red"
)

Labels

geom_label(
  aes(linetype = factor(vs), linewidth = factor(am)),
  text.colour = "black",
  border.colour = "blue"
)

Varying Fill

geom_area(aes(fill = continuous_var))  # gradient (R 4.1+)

New Stats

stat_manual()

make_centroids <- function(df) {
  transform(df, xend = mean(x), yend = mean(y))
}
stat_manual(geom = "segment", fun = make_centroids)

stat_connect()

geom_line(stat = "connect")           # stairstep
geom_ribbon(stat = "connect", alpha = 0.4)

# Custom connection shape
smooth <- cbind(x = seq(0, 1, length.out = 20)[-1],
                y = scales::rescale(plogis(x, 0.5, 0.1)))
stat_connect(connection = smooth)

Coord Reversal

coord_cartesian(reverse = "x")   # "y", "xy", "none"
coord_sf(reverse = "y")
coord_radial(reverse = "theta")  # "r", "thetar", "none"

Deprecations

Old New
fatten median.linewidth / middle.linewidth
draw_quantiles quantiles
geom_errorbarh() geom_errorbar(orientation = "y")
coord_trans() coord_transform()
borders() annotation_borders()
facet_wrap(as.table) facet_wrap(dir)
theme_get/set/update/replace() get/set/update/replace_theme()
last_plot() get_last_plot()
layer_data/grob/scales() get_layer_data/grob(), get_panel_scales()

Related Skills

Attack Tree Construction

Build comprehensive attack trees to visualize threat paths. Use when mapping attack scenarios, identifying defense gaps, or communicating security risks to stakeholders.

skill

Grafana Dashboards

Create and manage production Grafana dashboards for real-time visualization of system and application metrics. Use when building monitoring dashboards, visualizing metrics, or creating operational observability interfaces.

skill

Matplotlib

Foundational plotting library. Create line plots, scatter, bar, histograms, heatmaps, 3D, subplots, export PNG/PDF/SVG, for scientific visualization and publication figures.

skill

Scientific Visualization

Create publication figures with matplotlib/seaborn/plotly. Multi-panel layouts, error bars, significance markers, colorblind-safe, export PDF/EPS/TIFF, for journal-ready scientific plots.

skill

Seaborn

Statistical visualization. Scatter, box, violin, heatmaps, pair plots, regression, correlation matrices, KDE, faceted plots, for exploratory analysis and publication figures.

skill

Shap

Model interpretability and explainability using SHAP (SHapley Additive exPlanations). Use this skill when explaining machine learning model predictions, computing feature importance, generating SHAP plots (waterfall, beeswarm, bar, scatter, force, heatmap), debugging models, analyzing model bias or fairness, comparing models, or implementing explainable AI. Works with tree-based models (XGBoost, LightGBM, Random Forest), deep learning (TensorFlow, PyTorch), linear models, and any black-box model

skill

Pydeseq2

Differential gene expression analysis (Python DESeq2). Identify DE genes from bulk RNA-seq counts, Wald tests, FDR correction, volcano/MA plots, for RNA-seq analysis.

skill

Query Writing

For writing and executing SQL queries - from simple single-table queries to complex multi-table JOINs and aggregations

skill

Pydeseq2

Differential gene expression analysis (Python DESeq2). Identify DE genes from bulk RNA-seq counts, Wald tests, FDR correction, volcano/MA plots, for RNA-seq analysis.

skill

Scientific Visualization

Meta-skill for publication-ready figures. Use when creating journal submission figures requiring multi-panel layouts, significance annotations, error bars, colorblind-safe palettes, and specific journal formatting (Nature, Science, Cell). Orchestrates matplotlib/seaborn/plotly with publication styles. For quick exploration use seaborn or plotly directly.

skill

Skill Information

Category:Skill
Last Updated:1/18/2026