Feature matrix

Coverage of the ggplot2 and plotnine surface in Gribouille.

Context

Gribouille is a Typst package that implements a grammar of graphics on top of CeTZ. This page is the canonical coverage table: one row per public ggplot2 symbol, using the ggplot2 reference index as the axis. Status reflects what is currently in the package; Priority orders the remaining work.

Legend for Status:

  • βœ… implemented.
  • 🟑 partial or stubbed.
  • ⬜ missing.
  • ❌ out of scope for a static Typst backend (reason in Notes).

Legend for Priority (used to order future work):

  • P1 unlocks common plots and blocks other work.
  • P2 broadens expressiveness once P1 lands.
  • P3 nice-to-have or niche.
  • P4 deferred to the very end of the roadmap: requires a wasm helper or heavy numerical code that Typst cannot express natively. Wasm is a last resort, added only if a P4 feature is really needed and no native workaround exists. Until then every P4 row sits behind everything in P1 to P3.
  • βˆ… not planned.

How gribouille currently maps to ggplot2

Concept ggplot2 form gribouille form
Plot constructor ggplot(data, aes(...)) + layer + scale + theme. plot(data:, mapping:, layers:, scales:, coord:, facet:, theme:, width:, height:).
Layer addition + geom_point(). layers: (geom-point(), ...).
Aesthetic mapping aes(x = a, y = b, colour = c). aes(x: "a", y: "b", colour: "c").
Stat override stat = "bin" on a geom. stat: key on the layer dict, dispatched via src/stat/apply.typ.
Theme composition theme_minimal() + theme(...). theme: theme-minimal() (dict merged by merge-theme).

Feature matrix

Plot basics

ggplot2 gribouille symbol Status Priority Notes
ggplot() plot(...). βœ… β€” β€”
aes() aes(...). βœ… β€” Accepts x, y, colour, fill, size, alpha, linewidth, stroke, shape, linetype, group, label, xmin/xmax/ymin/ymax, xend/yend, xintercept/yintercept/slope, plus ggforce-style x0/y0/a/b/angle for geom-ellipse.
%+% / add_gg() β€” ❌ βˆ… Typst has no lazy plot object; composition is via function args.
ggsave() β€” ❌ βˆ… Typst owns the output pipeline.
qplot() / quickplot() β€” ❌ βˆ… Deprecated upstream.

Geoms

ggplot2 gribouille symbol Status Priority Notes
geom_point() geom-point. βœ… β€” β€”
geom_line() geom-line. βœ… β€” X-sorted connection of observations.
geom_path() geom-path. βœ… β€” Connects rows in input order.
geom_step() geom-step. βœ… β€” Stair-step interpolation; direction is "hv" (default) or "vh".
geom_col() geom-col. βœ… β€” Honours position = "stack"/"dodge"/"fill".
geom_bar() geom-bar. βœ… β€” Wraps geom-col with stat = "count" and position = "stack".
geom_histogram() geom-histogram. βœ… β€” Uses stat-bin.
geom_freqpoly() geom-freqpoly. βœ… β€” Line through stat-bin midpoints; bins and binwidth mirror geom-histogram.
geom_ribbon() geom-ribbon. βœ… β€” β€”
geom_area() geom-area. βœ… β€” Filled polygon between y = 0 and y along x; pulls the y-domain to include zero.
geom_smooth() geom-smooth. 🟑 βˆ… method = "lm" only; "loess" deferred (needs LOWESS solver, not feasible without wasm).
geom_boxplot() geom-boxplot. βœ… β€” Default stat = "boxplot" runs the per-group five-number summary; raw observations in, full box+whiskers+outliers out.
geom_violin() β€” ⬜ βˆ… Needs KDE; not feasible in pure Typst without wasm.
geom_density() / geom_density_2d() / geom_density_2d_filled() β€” ⬜ βˆ… Needs KDE; not feasible in pure Typst without wasm.
geom_dotplot() geom-dotplot. βœ… β€” Bins observations along x via stat-bindot, stacks one dot per observation upward inside each bin. binwidth (or bins), dotsize, and stackratio follow ggplot2 semantics; method = "histodot" only (dynamic-binwidth dotdensity deferred).
geom_jitter() geom-jitter. βœ… β€” Point wrapper that defaults position to "jitter".
geom_rug() geom-rug. βœ… β€” Tick marks at observations on selected sides (b/t/l/r).
geom_text() geom-text. βœ… β€” Reads the label aesthetic.
geom_label() geom-label. βœ… β€” Boxed text with fill, stroke, radius.
geom_rect() / geom_tile() geom-rect, geom-tile. βœ… β€” geom_raster() (a ggplot2 fast path for regular grids) is not exposed; use geom-tile.
geom_polygon() geom-polygon. βœ… β€” One closed polygon per group; fill via fill or scale.
geom_segment() geom-segment. βœ… β€” Maps x/y/xend/yend.
geom_curve() geom-curve. βœ… β€” Quadratic-bezier curved variant of geom-segment. curvature (signed fraction of chord length) controls bow side and magnitude; angle shifts the apex along the chord. Sampled into n polyline points (default 32).
geom_errorbar() geom-errorbar. βœ… β€” Vertical range with horizontal end caps.
geom_errorbarh() geom-errorbarh. βœ… β€” Horizontal range with vertical caps; mirrors geom-errorbar over (y, xmin, xmax).
geom_linerange() / geom_crossbar() / geom_pointrange() geom-linerange, geom-crossbar, geom-pointrange. βœ… β€” linerange has no caps, crossbar is a filled box with a thick median bar, pointrange is a marker plus linerange.
geom_abline() / geom_hline() / geom_vline() geom-abline, geom-hline, geom-vline. βœ… β€” Scalar or array intercepts. Trans-aware: under log10/sqrt, abline samples 64 points so the line follows the warp.
geom_blank() geom-blank. βœ… β€” No-op draw; trains scales from its data.
geom_function() geom-function. βœ… β€” Samples a Typst callable across the x-domain into a polyline.
geom_qq() / geom_qq_line() geom-qq, geom-qq-line. βœ… β€” Reference distribution selectable via distribution: "normal" (default), "uniform", "exponential". Reference line through 25th and 75th sample quantiles.
geom_quantile() geom-quantile. βœ… β€” Linear quantile regression at user-supplied Ο„ via brute-force LP-breakpoint search through (xα΅’, xβ±Ό) pairs. Defaults to (0.25, 0.5, 0.75). O(nΒ³) β€” workable for plot-sized inputs.
geom_count() geom-count. βœ… β€” Wrapper over stat-sum; one point per unique (x, y) sized by count.
geom_bin_2d() / geom_hex() geom-bin-2d, geom-hex. βœ… β€” Rectangular and pointy-top hex bins. Default fill aesthetic is count. Both accept scalar or (x, y) bins / binwidth.
geom_contour() / geom_contour_filled() geom-contour, geom-contour-filled. βœ… β€” Marching-squares iso-lines and per-cell Sutherland-Hodgman iso-bands over a regular (x, y, z) grid. bins, binwidth, breaks control level placement; saddle cells use centre-average disambiguation. Filled bands tile per cell so default stroke: none keeps the shading seamless.
geom_spoke() geom-spoke. βœ… β€” Polar counterpart of geom-segment: each row’s (angle, radius) gives the offset to the segment endpoint via xend = x + r * cos(angle). Reuses segment scaffolding for stroke, colour, alpha, linetype.
geom_map() / geom_sf() / geom_sf_label() / geom_sf_text() β€” ❌ βˆ… Maps and sf are out of scope.

Stats

ggplot2 gribouille symbol Status Priority Notes
stat_identity() stat-identity (implicit). βœ… β€” β€”
stat_count() stat-count. βœ… β€” β€”
stat_bin() stat-bin. βœ… β€” β€”
stat_smooth() stat-smooth. 🟑 βˆ… OLS only; "loess" deferred (needs LOWESS solver, not feasible without wasm).
stat_boxplot() stat-boxplot. βœ… β€” Per-x bucketing with R type-7 quantiles; outliers retained for the geom.
stat_summary() / stat_summary_bin() stat-summary, stat-summary-bin. βœ… β€” Per-x bucket or per-bin reduction via mean-se / mean-cl-normal / mean-sdl / median-hilow.
stat_ecdf() stat-ecdf. βœ… β€” Empirical cumulative distribution: one row per unique x with y = count_le_x / n.
stat_ellipse() stat-ellipse. βœ… β€” Per-group covariance ellipse: 2Γ—2 sample covariance, closed-form eigenvalues, axes scaled by sqrt(Ξ» Β· χ²(level, df=2)). Pair with geom-ellipse(stat: "ellipse").
stat_density() / stat_density_2d() / stat_density_2d_filled() / stat_ydensity() β€” ⬜ βˆ… Needs KDE; not feasible in pure Typst without wasm.
stat_contour() / stat_contour_filled() stat-contour, stat-contour-filled. βœ… β€” Reshapes long (x, y, z) rows into a regular grid. stat-contour emits iso-line segments grouped per level; stat-contour-filled emits one closed polygon per cell per band with level set to the band’s lower bound (so a continuous fill scale shades by height).
stat_bin_2d() / stat_bin_hex() / stat_summary_2d() / stat_summary_hex() stat-bin-2d, stat-bin-hex, stat-summary-2d, stat-summary-hex. βœ… β€” stat-bin-* emit per-cell counts; rectangular cells also emit (xmin, xmax, ymin, ymax). stat-summary-* reduce a z aesthetic to value per cell (fun: accepts "mean", "median", "sum", "min", "max", or a callable). All accept scalar or (x, y) bins / binwidth.
stat_qq() / stat_qq_line() stat-qq, stat-qq-line. βœ… β€” Reference distribution selectable via distribution: "normal" (default), "uniform", "exponential".
stat_quantile() stat-quantile. βœ… β€” Backing statistic for @geom-quantile; emits sampled fitted-line rows tagged with quantile/group per Ο„.
stat_function() stat-function. βœ… β€” Samples fun over x-limits; pairs with any geom that consumes (x, y) rows.
stat_unique() stat-unique. βœ… β€” Drops duplicate (x, y) rows; first occurrence wins.
stat_manual() / stat_align() / stat_connect() stat-manual, stat-align, stat-connect. βœ… β€” stat-manual runs a user closure on rows; stat-align resamples each group onto a shared x-grid (panel-level union + zero-crossings) for stacked area / ribbon; stat-connect inserts intermediate vertices between consecutive points (modes "hv" / "vh" / "mid" / "linear").
stat_sf() / stat_sf_coordinates() β€” ❌ βˆ… Out of scope.
after_stat() / after_scale() / stage() / from_theme() after-stat, after-scale, stage, from-theme. βœ… β€” from-theme resolves at _prepare-layer and pins into layer.params; after-stat accepts column-name strings and (row, ctx) closures; after-scale honoured on colour / fill / alpha / size / linewidth / stroke / shape / linetype; stage composes all three lanes.

Position adjustments

ggplot2 gribouille symbol Status Priority Notes
position_identity() implicit default. βœ… β€” β€”
position_stack() position-stack. βœ… β€” Consumed by geom-col.
position_dodge() position-dodge. βœ… β€” Uniform and variable-per-row-width cases both supported; per-row width column packs side-by-side slots within each bucket and shrinks proportionally if the total exceeds the bucket. Subsumes the ggplot2 dodge2 case.
position_dodge2() merged into position-dodge. ❌ βˆ… Dropped from the surface; position-dodge covers both cases.
position_fill() position-fill. βœ… β€” Stack normalised to 1 per x bucket.
position_jitter() position-jitter. βœ… β€” Deterministic seed-based offsets; only continuous columns are jittered.
position_nudge() position-nudge. βœ… β€” Fixed (x, y) shift on every row.
position_jitterdodge() position-jitterdodge. βœ… β€” Groups dodge then jitter within their slot; pair with geom-jitter via position: position-jitterdodge(...).

Annotations

ggplot2 gribouille symbol Status Priority Notes
annotate() annotate. βœ… β€” Sugar over a one-row layer; supports text, point, label, segment, rect, vline, hline, abline.
annotation_custom() / annotation_raster() β€” ❌ βˆ… Out of scope: geom-typst evaluates arbitrary Typst markup at a data position, covering both arbitrary content and image rasters natively.
annotation_logticks() β€” ❌ βˆ… Out of scope: superseded by guide_axis_logticks (P3, Guides section).
annotation_map() / borders() β€” ❌ βˆ… Maps out of scope.

Aesthetics (names consumed by aes())

ggplot2 gribouille Status Priority Notes
x, y x, y. βœ… β€” β€”
xmin, xmax, ymin, ymax xmin, xmax, ymin, ymax. βœ… β€” Exposed via aes() and trained like other positional aesthetics.
xend, yend xend, yend. βœ… β€” Folded into the x and y axis domains during scale training; consumed by @geom-segmentGitHub.
colour, fill colour, fill. βœ… β€” β€”
alpha mapped via aes(alpha: ...). βœ… β€” Per-row opacity applied through the colour/fill resolution chain in every drawing geom (point, line, path, step, area, ribbon, polygon, segment, rect, tile, errorbar/h, linerange, crossbar, pointrange, abline, hline, vline, rug, text, label, typst, ellipse, mark).
size mapped via aes(size: ...). βœ… β€” Per-row size resolution in geom-point (and wrappers geom-jitter/geom-count/geom-qq), geom-pointrange, geom-text, geom-label, geom-typst. Other geoms have no marker/text size to size and ignore the aesthetic.
shape shape via scale-shape. βœ… β€” Circle, square, triangle, diamond, cross, x, star, triangle-down palette; any other value renders as a literal glyph, so characters or emoji can serve as markers.
linetype linetype via scale-linetype. βœ… β€” Solid, dashed, dotted, dash-dotted, densely-dashed, loosely-dashed palette.
linewidth mapped via aes(linewidth: ...). βœ… β€” Per-row stroke thickness consumed by geom-line/path/step/segment/abline/hline/vline/errorbar/linerange/pointrange/rug.
stroke mapped via aes(stroke: ...). βœ… β€” Per-row marker outline thickness on geom-point. The layer’s stroke: parameter (length, dict, or auto) pins the value when set explicitly; auto (the default) routes through the stroke aesthetic. Paired with scale-stroke-continuous/-manual/-binned/-identity.
group group. βœ… β€” β€”
weight mapped via aes(weight: ...). βœ… β€” Per-row weights threaded into stat-count, stat-sum, stat-bin, stat-summary (mean/mean-se/mean-sd/mean-cl-normal helpers), stat-summary-bin, stat-ecdf, and stat-smooth (weighted least squares). Median and quantile-based reducers ignore weights for now.
lower, middle, upper, ymin, ymax, outliers computed by stat-boxplot, consumed by geom-boxplot. βœ… β€” Internal aesthetics carried between stat and geom.
Inline type coercion (aes(colour = factor(x)), aes(x = as.numeric(g))) as-factor("col") / as-numeric("col") inside aes(). βœ… β€” ggplot2 forces a mapping discrete or continuous at the aes() call site with factor() / as.numeric(). In gribouille, as-factor and as-numeric are dual-arity: called with (data, col) they rewrite the column across the whole plot, called with (col) from inside aes() they return a (kind: "mapping-ref", var: col, type: "discrete" \| "continuous") annotation that scopes the coercion to a single aesthetic. Scale training in src/scale/train.typ accepts either a plain string or the annotation dict via the mapping-ref-col / mapping-ref-type helpers, so the same numeric column can be continuous on x and discrete on colour in one plot.

Positional scales

ggplot2 gribouille symbol Status Priority Notes
scale_x_continuous() / scale_y_continuous() scale-x-continuous, scale-y-continuous. βœ… β€” β€”
scale_x_discrete() / scale_y_discrete() scale-x-discrete, scale-y-discrete. βœ… β€” β€”
scale_x_log10() / scale_y_log10() scale-x-log10, scale-y-log10. βœ… β€” Pre-stat: data is log-transformed before stats run, matching ggplot2 v4 / plotnine. Powers-of-10 break placement; sub-decade (2, 5) ticks emitted for narrow ranges.
scale_x_sqrt() / scale_y_sqrt() scale-x-sqrt, scale-y-sqrt. βœ… β€” Pre-stat warp; data is square-rooted before stats run.
scale_x_reverse() / scale_y_reverse() scale-x-reverse, scale-y-reverse. βœ… β€” Implemented by swapping the range endpoints during mapping.
scale_x_binned() / scale_y_binned() scale-x-binned, scale-y-binned. βœ… β€” Quantised continuous axis with ticks at bin midpoints.
scale_x_date() / scale_y_date() / scale_x_datetime() / scale_y_datetime() / scale_x_time() / scale_y_time() scale-x-date, scale-y-date, scale-x-datetime, scale-y-datetime, scale-x-time, scale-y-time. βœ… β€” Accepts ISO-8601 strings ("2024-01-15", "2024-01-15T08:30:00", "08:30") or numeric epoch input. Axis labels formatted via Typst datetime.display(date-format). Timezone offsets ignored.

Colour and fill scales

ggplot2 gribouille symbol Status Priority Notes
scale_colour_continuous() / scale_fill_continuous() scale-colour-continuous, scale-fill-continuous. βœ… β€” β€”
scale_colour_discrete() / scale_fill_discrete() scale-colour-discrete, scale-fill-discrete. βœ… β€” β€”
scale_colour_manual() / scale_fill_manual() scale-colour-manual, scale-fill-manual. βœ… β€” User-supplied palette array.
scale_colour_viridis_c/d/b() / scale_fill_viridis_c/d/b() scale-colour-viridis-c/d/b, scale-fill-viridis-c/d/b. βœ… β€” viridis, magma, plasma, inferno, cividis.
scale_colour_brewer() / scale_fill_brewer() scale-colour-brewer, scale-fill-brewer. βœ… β€” 24 ColorBrewer palettes (qualitative, sequential, diverging) via brewer-palette(name).
scale_colour_gradient() / gradient2() / gradientn() scale-colour-gradient, scale-colour-gradient2, scale-colour-gradientn (and fill counterparts). βœ… β€” Two-stop, diverging-around-midpoint, and n-stop gradients; legend colourbars match.
scale_colour_steps() / steps2() / stepsn() scale-colour-steps, scale-colour-steps2, scale-colour-stepsn, plus fill counterparts. βœ… β€” Binned variants of gradient/gradient2/gradientn.
scale_colour_grey() / scale_fill_grey() scale-colour-grey, scale-fill-grey. βœ… β€” Discrete grey ramp from start to end luminance.
scale_colour_hue() / scale_fill_hue() scale-colour-hue, scale-fill-hue. βœ… β€” OKLCh-spaced hues; near-equivalent to ggplot2’s HCL defaults.
scale_colour_distiller() / fermenter() scale-colour-distiller, scale-colour-fermenter, plus fill counterparts. βœ… β€” Continuous and binned Brewer; direction: -1 reverses.
scale_colour_identity() / scale_fill_identity() scale-colour-identity, scale-fill-identity. βœ… β€” Column values are passed through (hex strings or color values). No legend is drawn.

Other aesthetic scales

ggplot2 gribouille symbol Status Priority Notes
scale_alpha() / *_continuous() / *_discrete() / *_manual() / *_binned() scale-alpha-continuous, scale-alpha-manual, scale-alpha-binned, scale-alpha-identity. βœ… β€” Manual scale takes a per-level array of opacities; binned scale stays continuous with bin-snapped legend ticks.
scale_size() / scale_size_manual() / scale_radius() scale-size-continuous, scale-size-manual, scale-radius. βœ… β€” Manual scale takes a per-level array of Typst lengths; scale-radius is the linear value-to-radius alias.
scale_size_area() / scale_size_binned_area() scale-size-area, scale-size-binned-area. βœ… β€” resolve-size honours size-trans: "area" so radius scales with sqrt(value).
scale_size_binned() scale-size-binned. βœ… β€” Continuous mapping with bin-snapped legend ticks.
scale_shape() / scale_shape_manual() / scale_shape_binned() scale-shape, scale-shape-manual, scale-shape-binned. βœ… β€” _binned cuts a continuous variable into n-breaks bins, each bin gets one shape from the palette.
scale_linetype() / scale_linetype_manual() / scale_linetype_binned() / scale_linetype_continuous() / scale_linetype_discrete() scale-linetype, scale-linetype-manual, scale-linetype-binned, scale-linetype-continuous, scale-linetype-discrete. βœ… β€” _binned cuts a continuous variable into n-breaks bins; _continuous is an alias for _binned; _discrete is an alias for the default scale.
scale_linewidth() / scale_linewidth_manual() / scale_linewidth_binned() scale-linewidth-continuous, scale-linewidth-manual, scale-linewidth-binned, scale-linewidth-identity. βœ… β€” Manual scale takes a per-level array of Typst lengths; binned scale stays continuous with bin-snapped legend ticks.
scale_shape_identity() / scale_linetype_identity() scale-shape-identity, scale-linetype-identity. βœ… β€” Column values used as the shape / dash keyword directly.
scale_size_identity() / scale_alpha_identity() / scale_linewidth_identity() scale-size-identity, scale-alpha-identity, scale-linewidth-identity. βœ… β€” Column values used as the size / alpha / linewidth directly.

Labels and limits

ggplot2 gribouille symbol Status Priority Notes
labels() labels(title:, subtitle:, caption:, x:, y:, colour:, fill:, ...). βœ… β€” Axis names are injected into trained scale specs. Covers the role of xlab / ylab / ggtitle.
get_labs() β€” ❌ βˆ… Out of scope. ggplot2 introspects a lazy plot object; gribouille has no equivalent β€” labels() is a plain dict the user already holds.
lims() / x-limits() / y-limits() β€” ❌ βˆ… Use scale-x-continuous(limits:) / scale-y-continuous(limits:) directly.
expansion() / expand_scale() per-scale expand: argument. βœ… β€” Each positional scale’s expand: accepts a ratio (5%) for proportional padding, a length (5pt) for canvas-space padding, a relative (5pt + 5%) for both, or a (lo, hi) 2-tuple for asymmetric padding.
expand_limits() expand-limits. βœ… β€” Folds extension values into the trained continuous domain rather than replacing it.

Guides

ggplot2 gribouille symbol Status Priority Notes
Discrete guide_legend() for colour/fill automatic legend. βœ… β€” β€”
guide_colourbar() automatic colourbar. βœ… β€” Emitted when trained colour/fill is continuous.
guide_legend() customisation (nrow, ncolumn, reverse, …) guide-legend(title:, nrow:, ncolumn:, reverse:). βœ… β€” Plot-level binding via guides(colour: guide-legend(...)).
guide_coloursteps() automatic stepped colourbar. βœ… β€” Emitted automatically when a colour/fill scale carries binned: true (e.g., scale-colour-steps, scale-fill-fermenter, scale-colour-viridis-b): n-breaks discrete patches with ticks at the bin boundaries.
guide_bins() automatic binned ladder. βœ… β€” Emitted automatically when a size/alpha/linewidth/stroke/shape/linetype scale carries binned: true: one glyph per bin at the midpoint.
guide_axis() guide-axis(angle:, n-dodge:). βœ… β€” Honours angle and n-dodge on both x- and y-axis (y-dodge staggers across columns receding from the axis).
guide_axis_logticks() guide-axis-logticks(angle:, n-dodge:). βœ… β€” Opt-in via guides(x: guide-axis-logticks()) (or y:). Adds half-length minor ticks at sub-decade positions (2, 3, …, 9) when paired with transform: "log10"; no-op on linear axes. Inherits angle/n-dodge from @guide-axis.
guide_none() guides(<aes>: none). βœ… β€” Suppress a specific aesthetic’s legend, an x / y axis’s ticks and labels, or a radial theta / r axis’s labels, by passing none.
guide_axis_stack() guide-axis-stack(guides:, spacing:). βœ… β€” Stack multiple guide-axis / guide-axis-logticks rows on the same axis side; each sub-guide keeps its own angle/n-dodge.
guide_axis_theta() guide-axis-theta(angle:, minor-ticks:, cap:). βœ… β€” Bind via guides(theta: guide-axis-theta(...)) under coord-radial to rotate theta tick labels, emit half-step minor ticks, and draw an outer axis arc with optional "upper" / "lower" / "both" cap.
guide_custom() guide-custom(content, width:, height:, title:). βœ… β€” Free-form Typst content placed in the legend area; no associated scale. Right-side placement only in this slice; other positions are follow-up.
guides() top-level guides. βœ… β€” Threaded into plot(..., guides: guides(colour: guide-legend(...))).
sec_axis() / dup_axis() sec-axis, dup-axis. βœ… β€” Passed via secondary: on scale-x-continuous / scale-y-continuous. derive() deferred.
draw_key_*() glyph family draw-key-point, draw-key-line, draw-key-rect, draw-key-path, draw-key-blank. βœ… β€” Auto-dispatched by geom kind; legend swatches now match the layer’s visual.

Facetting

ggplot2 gribouille symbol Status Priority Notes
facet_wrap() facet-wrap. βœ… β€” scales = "fixed" (default), "free", "free_x", "free_y"; per-facet stats via partition-by-group.
facet_grid() facet-grid(rows:, columns:). βœ… β€” Strips on top (columns) and right (rows); shared scales only.
vars() β€” ❌ βˆ… Out of scope. ggplot2’s vars() quotes faceting variables for facet_wrap()/facet_grid(); gribouille’s facet-wrap("col") and facet-grid(rows: "col", columns: "col") take plain strings, so the wrapper is redundant.
labeller() / label_value() / label_both() / label_context() / label_wrap_gen() labeller, label-value, label-both, label-context, label-wrap. βœ… β€” Passed via labeller: on facet-wrap / facet-grid. label_parsed/label_bquote deferred.

Coordinates

ggplot2 gribouille symbol Status Priority Notes
coord_cartesian() coord-cartesian. βœ… β€” x-limits/y-limits override trained x/y domains (data is not dropped; out-of-range marks still render).
coord_fixed() coord-fixed. βœ… β€” Locks the aspect ratio so one x data unit equals ratio y data units. Honoured in non-faceted, facet-wrap (per-panel under free scales), and facet-grid renders.
coord_flip() coord-flip. βœ… β€” Swaps x and y at render time. Common geoms (point, line, col, bar, segment, abline/hline/vline) verified; less-common geoms inherit the swap and may need per-geom adjustment.
coord_polar() / coord_radial() coord-radial. βœ… β€” Pie, donut, rose, radar, radial scatter, paths, areas, ribbons, polygons, rect, tile, hex, ellipse, curve, spoke, dotplot, smooth, function, mark, typst, text/label, reference geoms (hline β†’ circle, vline β†’ ray, abline), errorbar / errorbarh / linerange / pointrange / crossbar / boxplot all render as polar wedges, spines and arc caps. geom-rug degrades to a no-op (axis-edge tassels don’t translate to polar). Replaces ggplot2’s legacy coord_polar().
coord_transform() coord-transform. βœ… β€” Per-axis post-stat warp ("identity", "log10", "sqrt", "reverse"). Distinct from scale_x_log10() and friends, which are pre-stat. When both are set on the same axis, the scale’s pre-stat warp wins.
coord_map() / coord_quickmap() / coord_sf() β€” ❌ βˆ… Maps out of scope.

Themes

ggplot2 gribouille symbol Status Priority Notes
theme_minimal() theme-minimal. βœ… β€” β€”
theme_classic() theme-classic. βœ… β€” β€”
theme_void() theme-void. βœ… β€” β€”
theme_grey() / theme_bw() / theme_linedraw() / theme_light() / theme_dark() theme-grey, theme-bw, theme-linedraw, theme-light, theme-dark. βœ… β€” British spelling only: no theme-gray alias.
theme() theme(..fields). βœ… β€” Translates element_* dicts into flat keys consumed by merge-theme.
element_blank() / element_rect() / element_line() / element_text() element-blank, element-rect, element-line, element-text. βœ… β€” Plus element-typst() (gribouille extension that auto-evaluates Typst-markup strings on text surfaces).
element_geom() element-geom(fill:, colour:, linewidth:, ink:, paper:, accent:). βœ… β€” Layer-default record stored on theme.geom; honoured by every supporting geom with ggplot2 v4-style role inheritance (fill/colour are global overrides; ink/paper/accent shift the role colours each per-geom default falls back to).
element_polygon() / element_point() β€” ⬜ βˆ… ggplot2 v4 ships these strictly as inheritance-tree parents in theme(polygon, point); no built-in plot component renders them. Gribouille has no extension-registration system, will revisit when one appears.
margin() / margin_part() / margin_auto() margin. βœ… β€” Per-side spacing record consumed by element-text / element-typst (text gaps) and element-rect (inset / outset offsets). Single margin() covers all three R helpers: every side defaults to auto (falls through to the consuming surface’s default), so margin() resets to defaults, margin(left: 2cm) overrides only the named side, and margin(top: 0pt, right: 0pt, bottom: 0pt, left: 0pt) pins every side.
rel() β€” ❌ βˆ… Out of scope. Typst supports relative sizing natively via em (relative to text size) and % (relative to container), so a rel() wrapper is redundant.
theme_get() / theme_set() theme-get, theme-set. βœ… β€” Global theme state via Typst’s state() (layout-time). plot(theme: ...) always takes precedence over theme-set().
theme_update() / theme_replace() / %+replace% β€” ❌ βˆ… Out of scope. ggplot2’s update/replace mutate the global theme record; gribouille users compose themes by calling theme-set(theme(...)) with the merged record explicitly.
theme_sub_axis*() / theme_sub_legend() / theme_sub_panel() / theme_sub_plot() / theme_sub_strip() theme-sub-axis, theme-sub-axis-x, theme-sub-axis-y, theme-sub-axis-bottom, theme-sub-axis-top, theme-sub-axis-left, theme-sub-axis-right, theme-sub-legend, theme-sub-panel, theme-sub-plot, theme-sub-strip. βœ… β€” Shortcut groups expanding to family-prefixed theme(...) keys.

Helpers

ggplot2 gribouille symbol Status Priority Notes
cut_interval() / cut_number() / cut_width() cut-interval, cut-number, cut-width. βœ… β€” Pure helpers; bin labels of the form "(lo,hi]".
resolution() resolution. βœ… β€” Zero-aware by default; matches ggplot2.
mean_se() / mean_cl_normal() / mean_sdl() / median_hilow() mean-se, mean-cl-normal, mean-sdl, median-hilow. βœ… β€” mean-cl-normal panics on conf != 0.95. mean_cl_boot deferred.

Programming and extension

ggplot2 gribouille symbol Status Priority Notes
ggproto() / ggproto_parent() β€” ❌ βˆ… S3/R6 pattern; Typst uses dict-of-functions instead.
aes_() / aes_string() / aes_q() β€” ❌ βˆ… Deprecated upstream.
print.ggplot / plot.ggplot β€” ❌ βˆ… Typst handles rendering.
autoplot() / autolayer() / fortify() / map_data() / automatic_plotting β€” ❌ βˆ… R S3 dispatch.
get_alt_text() get-alt-text. βœ… β€” Reads spec.alt set via the new plot(..., alt: ...) parameter.

Bundled datasets

ggplot2 gribouille Status Priority Notes
mpg, economics mpg (30 rows), economics (24 rows). βœ… β€” Small subsets bundled for examples; values plausible but not exact.
Other datasets (diamonds, economics_long, faithfuld, midwest, msleep, presidential, seals, txhousing, luv_colours) β€” ❌ βˆ… Bundling additional datasets bloats the package; users can load their own from CSV. The shipped trio (mpg, penguins, economics) covers the docs and tests.

Extensions and native

Items outside the ggplot2 surface: ggforce ports and gribouille-native conveniences.

Source gribouille symbol Status Priority Notes
ggforce::geom_ellipse() geom-ellipse. βœ… β€” Standalone ellipse from (x0, y0, a, b, angle) parameters; samples 64 vertices per row and renders through the polygon draw path. Axes auto-extend to enclose every ellipse.
ggforce::geom_mark_*() family geom-mark. βœ… β€” Unified annotation geom with method: "circle" / "ellipse" / "hull" / "rect" covering _circle/_ellipse/_hull/_rect. method avoids clash with shape aesthetic. Hull uses Andrew’s monotone chain; circle is smallest enclosing; ellipse is bbox-aligned.
native (no upstream) geom-typst. βœ… β€” Sibling of geom-text that always evaluates the label aesthetic as Typst markup. Both routings work: annotate("typst", label: "...") and annotate("text", label: typst("...")) (the typst() tag survives annotate’s per-row dataset by being preserved on the mapping column reference).

Coverage at a glance

  • Plot basics: plot() and aes() covering x, y, colour, fill, size, alpha, group.
  • Geoms: point, line, path, step, col, bar, histogram, freqpoly, ribbon, area, boxplot, dotplot, jitter, rug, text, label, typst, rect, tile, bin-2d, hex, contour, contour-filled, polygon, segment, curve, spoke, ellipse, mark, errorbar, errorbarh, linerange, crossbar, pointrange, abline, hline, vline, blank, function, qq, qq-line, quantile, count; geom-smooth covers method = "lm" only.
  • Stats: stat-identity, stat-count, stat-sum, stat-bin, stat-bin-2d, stat-bin-hex, stat-bindot, stat-boxplot, stat-contour, stat-contour-filled, stat-summary, stat-summary-bin, stat-summary-2d, stat-summary-hex, stat-ecdf, stat-ellipse, stat-qq, stat-qq-line, stat-quantile, stat-unique, stat-function, stat-manual, stat-align, stat-connect; stat-smooth covers method = "lm" only.
  • Positions: identity, stack, fill, dodge (uniform and variable widths), jitter, jitterdodge, nudge.
  • Annotations: annotate() with text, point, label, segment, rect, vline, hline, abline.
  • Positional scales: continuous, discrete, log10, sqrt, reverse, date, datetime, time, on x and y.
  • Colour and fill scales: continuous, discrete, manual, viridis (c/d/b), brewer, gradient, gradient2, gradientn, grey, hue, distiller, identity.
  • Other aesthetic scales: shape and linetype (with manual and identity variants); linewidth, alpha, and size (continuous, manual, binned, identity); size also has scale-size-area, scale-size-binned-area, and the scale-radius linear alias.
  • Coords: coord-cartesian (with x-limits/y-limits), coord-fixed, coord-flip, coord-radial (pie/donut/rose/radar), and coord-transform (post-stat per-axis warp).
  • Facets: facet-wrap (fixed/free/free_x/free_y scales) and facet-grid (shared scales only).
  • Themes: theme-minimal, theme-classic, theme-void, theme-grey, theme-bw, theme-linedraw, theme-light, theme-dark, theme-test, plus theme() with element-blank, element-rect, element-line, element-text, and element-geom driving every supporting geom’s default fill/colour/linewidth with ggplot2 v4-style role inheritance through ink/paper/accent. Family-scoped shortcut groups: theme-sub-axis (and per-axis / per-side variants), theme-sub-legend, theme-sub-panel, theme-sub-plot, theme-sub-strip.
  • Guides: guide-legend with title/nrow/ncol/reverse, automatic guide-colourbar for continuous colour and fill, guide-axis (x and y) with guide-axis-logticks for log10 minor ticks, guide-axis-stack to stack multiple axis-guide rows on one side, guide-axis-theta for radial theta tick labels and outer axis arc, guide-custom for free-form Typst content in the legend area, a top-level guides() binder, and none to suppress a specific aesthetic’s legend.
  • Helpers: cut-interval, cut-number, cut-width, resolution, mean-se, mean-cl-normal, mean-sdl, median-hilow.
  • Datasets: mpg (30 rows) and economics (24 rows).

How this page is updated

Every implementation slice flips the Status column for every row it touches in the same commit as the code.

Back to top