Changelog
Source:NEWS.md
erplots 0.2.0
CRAN release: 2026-10-04
New features
- Added
er_tte(), a third mini-grammar (alongsideer_plot()/er_vpc()) for Kaplan-Meier/survival-over-time figures, built around a time axis, a survival-probability axis, and an optional discretestratify_by. Five singleton layers:er_tte_add_curve()(the KM step curve + confidence band),er_tte_add_censor()(censoring tick marks),er_tte_add_risktable()(a number-at-risk panel stacked below the curve),er_tte_add_summary()(a corner-placed text/label annotation – a log-rank test by default, or subject/event counts or a fitted model’s coefficients/goodness-of-fit viastyle), ander_tte_add_model()(a fitted parametricS(t)curve/ribbon overlay).er_tte_theme()styles labels, titles, axis limits, formatters, the legend key, and panel heights, mirroringer_plot_theme()/er_vpc_theme(). See the newplot-ttevignette. - Added
er_predict_survival(), a fourth model-interface generic (see?er_model_interface) poweringer_tte_add_model()’sS(t)overlay. The new companion packageertte(GitHub-only, likeerglm/emaxnls, but not a declaredSuggests/Remotesdependency oferplots) implements it, alongside the existinger_predict()/er_simulate()/er_summary()methods. -
cut_quantile()/cut_exposure_quantile()gain atiesargument controlling how a value that sits exactly on an interior quantile break is assigned ("upward", the default and prior behaviour;"downward"; or"split-even", which randomly balances tied values between the two candidate bins), plus an opt-inseedargument for reproducing"split-even"’s random tie-break. The resolved rule is recorded as a"ties"attribute on the returned factor. -
cut_quantile()/cut_exposure_quantile()gain aquantile_typeargument, passed straight through to [stats::quantile()]’s owntypeargument for computing the quantile break points. Defaults to7(unchanged prior behaviour) and is recorded as a"quantile_type"attribute on the returned factor. -
cut_quantile()/cut_exposure_quantile()gain alabellerargument for customising quantile-bin labels: a function called aslabeller(n, breaks), or a character vector used directly. Defaults toNULL(unchanged"Q1"/"Q2"/… labelling);cut_exposure_quantile()’s separate"Placebo"level is untouched bylabeller. -
er_plot_add_quantiles()/er_plot_add_groups()gainties/quantile_type/labellerarguments, forwarded tocut_exposure_quantile()/cut_quantile(). These are local to each call – they aren’t required to agree across differenter_plot_add_groups()calls, or wither_plot_add_quantiles()– except in one case:er_plot_build()now warns ifer_plot_add_groups()bins the exposure variable itself differently thaner_plot_add_quantiles()does, since the two panels would then show inconsistent quantile bins for the same variable. -
er_vpc()gainsties/quantile_type/labellerforplot_by, plus aseedargument for reproducing a"split-even"tie-break. Unlike theer_plot_add_quantiles()/er_plot_add_groups()arguments above, these live oner_vpc()itself rather than oner_vpc_add_observed()/er_vpc_add_simulated(), since the observed and simulated layers must always binplot_byidentically –er_vpc_add_simulated()’s ownseedargument now also seeds its independent"split-even"tie-break. -
er_vpc()gains an optionalstratify_byfor faceting a VPC into one panel per discrete stratum, mirroringer_plot()’s own stratification (facet-only here, since a VPC has no colour/fill precedence rule to reconcile). Errors ifstratify_byresolves to the same variable asplot_by. -
er_style_tag()gains alabelargument for registering a builder under a short string (e.g.label = "logrank"), so the corresponding_add_*()function’sstyleargument can be given that string instead of the function itself (e.g.er_plot_add_model(mod, style = "spaghetti")in place ofstyle = er_style_model_spaghetti). Every built-in builder across all three grammars is tagged with one; seeer_style_labels()to list what’s registered (optionally filtered to onelayer), and?er_style_tagfor the full naming/lookup contract.labelrequireslayerto also be set in the same call, since the registry is keyed by(layer, label), notlabelalone. A newoverwriteargument (defaultFALSE) controls what happens when re-registering a(layer, label)pair already assigned to a different function: errors by default;overwrite = TRUEreplaces it unconditionally. Re-registering the identical function is always a silent no-op regardless ofoverwrite.
Improvements
-
er_style_vpc_observed_mean_errorbar()/er_style_vpc_simulated_mean_errorbar()gain an opt-inshow_label/label_sizepair that draws each bin’s formatted rate/mean above its error bar, makinger_vpc_theme()’sformat_percent/format_numberarguments actually visible (#22). -
er_style_tte_risktable_text()gains an opt-inshow_percentargument that appends each break’s number at risk as a percentage of its stratum’s baseline size, usinger_tte_theme()’sformat_percent(#22). -
emaxnlsis back inSuggests/Remotes(pinned toemaxnls (>= 0.1.1.9000), the GitHub development version), and its gated examples in?erplots_dataare reinstated, now thatemaxnlsregisters theer_predict()/er_simulate()/er_summary()methods. It had been stripped for the 0.1.0 CRAN submission, ahead of that registration landing.
Breaking changes
-
er_style_tag()’szorderargument is renamed todraw_order(same"foreground"/"background"values); a builder tagged with the old name needs updating (e.g.er_style_tag(fn, draw_order = "background")in place ofzorder = "background")).layoutis split into two independent arguments:layoutkeeps its existing"overlay"/"panel"meaning for a data-layer builder, while a VPC observed/ simulated builder’s"categorical"/"continuous"distinction moves to a newvpc_layoutargument – the two had shared one argument and attribute despite meaning unrelated things. See?er_style_tag. -
er_style_tag()’slayervalues are renamed to be grammar-prefixed:"model"/"summary"/"quantile"/"data"/"group"(er_plot()) become"plot_model"/"plot_summary"/"plot_quantile"/"plot_data"/"plot_group";"observed"/"simulated"(er_vpc()) become"vpc_observed"/"vpc_simulated";"curve"/"censor"/"risktable"(er_tte()) become"tte_curve"/"tte_censor"/"tte_risktable"."tte_model"/"tte_summary"are unchanged (already grammar-prefixed). A custom builder tagged with one of the old values needs updating; see?er_style_tag. -
stratify_bymust now name a discrete/categorical variable iner_vpc(); a numeric column errors instead of being automatically split into quantile bins, and then_strataargument is removed. Bin a continuous covariate yourself first withcut_quantile()/cut_exposure_quantile(), which also gives full control over bin count, tie-breaking, and labels – see?er_vpc. (er_tte()’s ownstratify_byhas the same discrete-only requirement from the outset, being new in this release.) -
style/keep_strata’s argument position is standardised across everyer_plot_add_*()/er_vpc_add_*()/er_tte_add_*()layer function:stylenow always comes immediately afterobjectand any required model/grouping argument, andkeep_strata(where the layer has one) always comes immediately afterstyle.conf_level(where the layer has one) always comes immediately afterkeep_strata, ahead of any layer-specific argument such aser_plot_add_quantiles()’sbinsorer_tte_add_model()’stime_grid. Calls that name these arguments (the documented usage) are unaffected; positional calls that relied on the previous ordering will need updating. -
er_vpc()’sstratify_byargument moves to immediately afterresponse, matching whereer_plot()/er_tte()already place their ownstratify_by; it previously sat afterplot_by’s binning arguments (plot_by/n_bins/ties/quantile_type/labeller). Calls that namestratify_by(the documented usage) are unaffected. - The position of
...relative to a builder’s own named arguments is standardised to always come last, across every built-iner_style_*()builder:er_style_model_ribbonline()/_line()/_spaghetti(),er_style_data_overlay()/_boxjitter()/_hex(),er_style_tte_curve_km(),er_style_tte_censor_ticks(),er_style_tte_risktable_text(),er_style_tte_model_line(), ander_style_tte_summary_logrank()previously placed...immediately aftertheme, ahead of their own style-specific arguments, unlike every other built-in builder. Calls that name these arguments (the documented usage) are unaffected. - The “number of quantile bins” argument is renamed to
n_binseverywhere, matchinger_vpc()’s existing name:binsiner_plot_add_quantiles()/er_plot_add_groups(), andnincut_quantile()/cut_exposure_quantile(), all becomen_bins. A customlabellerfunction is now called aslabeller(n_bins, breaks)rather thanlabeller(n, breaks)– since this call is positional, only the documentation changed; existing customlabellerfunctions keep working regardless of their own parameter names.er_style_data_hex()’s ander_style_group_histogram()’s ownbinsarguments (2D-hexbin/histogram bin counts, forwarded straight to the matchingggplot2geom) are unrelated and unchanged. -
er_style_data_overlay()’s ander_style_tte_censor_ticks()’ssizeargument (a plotted point’s size) is renamed topoint_size, matching the quantile/VPC builder family’s existing name for the same concept (er_style_quantile_errorbar(),er_style_vpc_observed/ simulated_mean_errorbar(), etc.) and the package’s own<thing>_sizeconvention (label_size,text_size,jitter_size). -
er_style_group_linerange()’ssizeargument is renamed toscale_factor, since it isn’t a point size at all – it’s a single multiplier applied to three different elements (a dot and two line ranges) at three different ratios, so neithersizenorpoint_sizedescribed it accurately. -
er_style_group_linerange()’salpha_dot/alpha_inner/alpha_outerare renamed todot_alpha/inner_alpha/outer_alpha, matching the<thing>_alphasuffix order used by every other alpha argument in the package (ribbon_alpha,box_alpha,jitter_alpha).
Bug fixes
-
er_plot_add_model()’s curve/ribbon no longer goes stale afterer_plot_theme(xlim = ...)narrows or widens the exposure axis once the model layer has already been added – the prediction grid is now recomputed at build time rather than cached from add-layer time (#14). - The data, quantile, and group layers now drop (and warn about) any observations falling outside
er_plot_theme(xlim = )/ylim = ), instead of silently handing them to a geom that renders past the visible panel with no visual cue (#16). -
er_vpc_add_observed()/er_vpc_add_simulated()summary markers falling outsideer_vpc_theme(xlim = )/ylim = )are now dropped, with a warning, instead of silently drawn past the panel (#17). -
er_plot()now errors clearly whenstratify_bynames a numeric column, instead of silently mapping it to a continuous colour scale (which broke every stratified builder’s discrete-groups assumption – ribbons, per-stratum lines, dodging – with no warning).stratify_byhas always been documented as requiring a discrete variable; this was simply never validated. -
er_plot_add_groups()’sbinsargument now actually controls the number of quantile bins used for a continuous grouping variable. Previously documented but silently ignored – every continuous grouping variable was always split intocut_quantile()/cut_exposure_quantile()’s own default of 4 bins, regardless of whatbinswas set to. -
er_style_quantile_errorbar_vlines()/er_style_quantile_pointrange_vlines()’s bin-boundary lines/labels are now dropped (and warn), like every other layer’s out-of-range markers, when they fall outsideer_plot_theme(xlim = ), instead of silently landing off the visible panel with no cue (#16).
Documentation
-
?er_style_tagis rewritten to describe the mechanism as a whole – the shared self-declaration system every built-in builder acrosser_plot()/er_vpc()/er_tte()carries – rather than describing each argument in isolation. - Added
?er_style_vpc/?er_style_tte, documenting the shared builder interface forer_vpc()/er_tte()builders, alongside the existing?er_styleforer_plot(). Previously this material was scattered across each builder family’s own help page. - Fixed several cross-reference links in the pkgdown articles that previously rendered as literal bracketed text instead of a hyperlink.
- Every layer-adding function (
er_plot_add_model(),er_plot_add_summary(),er_plot_add_quantiles(),er_plot_add_data(),er_plot_add_groups(),er_vpc_add_observed(),er_vpc_add_simulated(), and all fiveer_tte_add_*()functions) now documents a “Styles” table listing every registeredstylelabel for that layer, linking straight to each builder’s own help page.
erplots 0.1.2
CRAN release: 2026-09-09
Addresses CRAN reviewer feedback on the 0.1.1 submission. User-facing changes:
-
er_plot_add_data()’s two jittered builders (er_style_data_overlay(),er_style_data_boxjitter()) no longer hard-code a specific RNG seed (previously a literal1234LinR/er-plot-layer.R, used so that repeatedplot()calls on the same object always showed identical jitter). Seeding is now opt-in only: passseed = <value>througher_plot_add_data()’s own...for reproducible jitter across rebuilds of the same object; with noseed(the default), jitter draws from the ambient RNG stream and differs from one build to the next, like any other jittered geom. -
er_plot_add_groups()’s jittered builders (er_style_group_boxjitter(),er_style_group_violinjitter()) gain the same opt-inseedsupport, for consistency – their jitter previously had no seed control at all.withrmoves fromSuggeststoImportsto support this.
erplots 0.1.1
- No user-facing changes. Fixes a documentation issue flagged by CRAN’s Debian pretest check.
erplots 0.1.0
Initial CRAN submission.
er_plot(): the plotting mini-language
-
er_plot()builds a fluent, pipe-based specification for exposure-response plots, generalised across binary, continuous, and count responses (response_type = c("auto", "binary", "continuous", "count"), auto-detected when not supplied). - Six pipeline verbs attach layers to the specification – nothing is drawn until
er_plot_build()/print()/plot()– and pipe order never affects the built plot:-
er_plot_add_model()– a model curve/ribbon. -
er_plot_add_summary()– a corner-placed text/label annotation (a model-derived statistic, or a plain observation count). -
er_plot_add_quantiles()– a quantile-binned response-rate/mean summary with confidence interval. -
er_plot_add_data()– a raw-data layer, either an overlay drawn on the main panel or one or more panels stacked below it. -
er_plot_add_groups()– stacked panels showing the exposure distribution per group variable (the one additive, non-singleton layer).
-
-
stratify_bysplits colour/facet encoding across strata, following a documented colour/facet precedence rule (seevignettes/articles/design.Rmd). -
er_plot_theme()styles labels, titles, axis limits, discrete/ continuous colour and fill palettes, formatters, the legend key glyph, and relative panel heights, without changing which variable drives which aesthetic.
The model interface
- Any model implementing
er_predict()can be visualised; additionally implementinger_simulate()and/orer_summary()enables uncertainty spaghetti plots/VPCs and model-derived summary annotations. See?er_model_interface. - erplots never fits a model itself – it is designed to work alongside companion packages that implement the interface, such as
erglm(GLM-based exposure-response models) andemaxnls(Emax/sigmoidal dose-response models).
The builder system
- Every layer-adding function accepts a
styleargument (aer_style_*()builder function) that can be swapped for another built-in or a fully custom builder, with a documented interface (?er_style) and self-declared metadata viaer_style_tag(). - Built-in builders cover multiple visual idioms per layer, e.g. ribbon/line/spaghetti model curves, p-value/n/coefficients/ goodness-of-fit summaries, errorbar/pointrange quantile summaries (with boundary-labelled
_vlinesvariants), overlay/hexbin/ boxjitter data layers, and boxplot/violin/histogram/boxjitter/ violinjitter group panels.
er_vpc(): the visual predictive check mini-grammar
-
er_vpc()|>er_vpc_add_observed()|>er_vpc_add_simulated()mirrorser_plot()’s object/layer/builder architecture for building visual predictive checks, with an optionalstratify_byfor faceted panels. - Three visual idioms are available via
style: an adaptive mean/ errorbar default, a continuous-x percentile-band idiom, and an adaptive quantile-errorbar idiom. -
er_vpc_theme()styles labels, titles, axis limits, and formatters.