check_figure(), an accessibility and honesty audit
of the figure you are about to submit. Until now the package could vouch
for its palette and say nothing about a finished plot, which is the
thing a reader sees. Give it anything a depictr function returns,
including a plot extended afterwards with +, and it
introspects the build and returns a tidy table. The rows cover the
separability of the encoding colours under each dichromacy and in
greyscale, the smallest text size against a stated physical output
width, the WCAG contrast of the text and of the geometry against their
backgrounds, and whether any distinction is carried by colour alone.
Every row carries the value it measured beside the threshold it was
measured against, so a verdict can be argued with.simulate_cvd()
and palette_safety() were internal here while the Python
twin exported both, so the advertised parity did not hold. They now
match in name, arguments, return shape and refusal wording.
simulate_cvd() gains a severity argument and
returns lower-case hex, as the Python twin does.
palette_safety() returns the full report, naming the worst
condition, the closest pair and the verdict. The old return was a bare
vector of distances.#e69f00) and sky blue
(#56b4e9) differ by 0.79 in CIE lightness, so a
black-and-white printer renders them as the same grey. The Okabe-Ito
guarantee is about hue confusion and was never a claim about greyscale.
The threshold stays where it is, and vignette("depictr")
now states the limitation where the claim is made, so the package’s own
defaults are held to the same standard as anybody else’s.quantile_residuals() produced nonsense for a
cbind(successes, failures) binomial model. The two-column
response matrix was flattened to a vector and the raw success counts
were then multiplied by the trial totals a second time, so the residuals
of a well-specified model centred far from zero and the Q-Q diagnostic
looked catastrophically misspecified. The matrix response now supplies
its counts and trial totals directly, and the residuals are standard
normal again where they should be.ridgeline_plot() stacked its overlaps upside down. The
row sort meant to draw the top ridge first is a no-op, because ggplot2
draws ribbon groups in factor-level order, so each upper ridge painted
over the one below it, the opposite of the conventional ridgeline
overlap. The draw order is now carried by the group aesthetic, with the
colour assignment unchanged.random_effects_plot(sort = TRUE) froze every facet in
the first facet’s order. With more than one term the level factor was
shared across panels, so only the first panel came out sorted and the
rest zig-zagged. Each facet now orders its own levels, with the plain
level names kept on the axis.title in
power_curve_plot() is no longer run through
format_terms(), which turned a colon into a multiplication
sign and blanked underscores. Only a title recovered from the
power-curve object, which is a raw term name, is tidied.survival_plot() drew a phantom arm for a group that
does not exist. An NA in group became a level
of its own, matching no observation, so the plot gained an all-censored
curve for a group nobody was in, and under logrank = TRUE
it failed outright. Missing groups are now dropped with a message saying
how many.survival_plot() silently discarded non-finite follow-up
times. Dropping a case from a Kaplan-Meier fit changes the denominator,
and so every step of the curve and every cell of the number-at-risk
table, while the figure carries no trace of it. It now refuses them,
with the same message as the Python twin, since whether to drop or
impute is the analyst’s decision to make. This replaces a silent drop,
so it is a behaviour change for anyone who relied on the old
handling.depictr_palette() interpolated past its accessibility
guarantee without saying so. Beyond the eight Okabe-Ito base colours the
palette is a ramp, and the colour-vision-deficiency guarantee that is
this package’s reason for existing stops holding, so the interpolated
palette fails the package’s own safety check. It now warns at the point
of interpolation, and only for the built-in palette, since a
user-supplied one carries no such claim. The documentation is qualified
to match.summary_table() counted missing-group records in
Overall and in no group column, so the per-group sizes
silently fell short of the headline N. They now get a
Missing column of their own.compare_models(facet = TRUE) now honours
depictr_options(reference = ) for its per-panel reference
line. seasonal_plot() no longer labels a frequency-7 series
Mon..Sun, an alignment a plain ts cannot know. And a
mistyped labels key now warns, so the raw parameter name no
longer sits on the plot.survival_plot() now says when it drops observations
with a missing status, in the wording of the missing-group message. The
drop was previously silent. A status that is missing for every
observation is an error. This brings the third kind of incomplete
survival input into line with the other two, a missing group being
announced and a non-finite time refused.silhouette_plot() checks that clusters has
one entry per row of data before dropping incomplete rows.
A vector sized to the complete rows used to slip past the late check,
because subsetting it with the logical index padded it with
NA, and then died in the distance computation. It is now
refused with the same message cluster_plot() uses.tidy_estimates() no longer fails on a rank-deficient
lm with a raw “differing number of rows” error.
confint() keeps aliased terms as NA rows while
coef(summary()) drops them, so the intervals are now cut to
the estimated terms, with a message naming the aliased terms that were
left out.cluster_plot() and k_diagnostic() drop
zero-variance columns with a message when scale = TRUE, as
correlation_heatmap() already did, so a raw k-means error
no longer escapes. k_diagnostic() now names the values of
k_range it cannot evaluate instead of dropping them from
the search without a word, and explore_pairs() labels an
undefined correlation n/a where it once printed
r = NA beside a raw stats::cor() warning.model_report() at all, because
patchwork::free(type =, side =) arrived in 1.3.0.gain_plot() documents that the perfect-model reference
line is drawn for a single model only, which is what the code has always
done, and a test now pins it. The line bends at the prevalence of the
outcome, and overlaid models need not share a prevalence.model_fit_table() documents that a single model is
enough, which is what the code always accepted, and
raincloud_plot() no longer claims to be built from base
graphics primitives: like ridgeline_plot(), it is base R
and ggplot2 alone.?depictr again lists every exported function
(scale_fill_depictr() and the
scale_color_depictr() alias were missing), the README no
longer describes the Python package as a feature-parity twin (its own
README says otherwise), CONTRIBUTING no longer claims the maintenance
workflows close their own issues, and the
standardise = TRUE axis label now names the x-only
convention the figure uses.vif_plot() restricts its scale to the severity levels
present, which removes an empty key entry from the rendered figure.depictr_palette()
returning the palette’s hex colours directly, ready for
scale_fill_manual() or a base-graphics col =
argument, and shows depictr_options() setting defaults for
every later plot and returning the previous values, so the earlier look
can be put back afterwards.vignette("diagnostics-and-uncertainty") saves an
arranged panel with save_plot(), which writes at a
print-ready 300 dpi by default and creates any missing directories.vignette("multivariate-and-survival") adds
k_diagnostic(method = "gap"), which compares within-cluster
dispersion against a null reference and so, unlike the other two
criteria, can support k = 1.vignette("time-series") adds classical decomposition,
which holds the seasonal component fixed across the series where STL
lets it evolve from year to year.optimizer_fixef_plot() and
power_curve_plot() reference pages describe what each plot
shows. Both pages previously described the prototype gists the plots
grew from.roc_curve_plot() rejects a ci that
resolves to fewer than one bootstrap resample, with a clear error. Until
then it drew an all-NA band and an [NA, NA]
AUC annotation, saying nothing.wellbeing_survey, region now shifts stress and
income, which flow through to life satisfaction. The region-grouped
plots (faceted densities, ridgelines, the region dendrogram) therefore
compare four distinct distributions where earlier they compared four
samples of one. The bundled datasets are regenerated by
data-raw/generate_datasets.R as before.inst/CITATION and
CITATION.cff) carries the Zenodo concept DOI, and the
citation title uses sentence case.?depictr) lists every exported
function and all five bundled datasets. Previously several functions and
two datasets were missing.vif_plot() example fits deliberately collinear
predictors, so the plot shows inflated VIFs sitting above the threshold
line. The earlier example produced near-identical bars around 1, with
the line off the axis.depictr_options() describes what brand and
accent actually drive, and depictr_palette()
notes that qualitative colours interpolated beyond the base set are not
guaranteed to stay distinguishable under colour-vision deficiency.lift_plot() documents its own top-right inside-legend
corner rather than inheriting gain_plot()‘s bottom-right
wording, and DESCRIPTION notes that composite panels return
’patchwork’ objects.LICENSE.md carries the full MIT text
so the site’s licence page renders in full, as in the sibling
packages.posterior_plot(),
residual_diagnostics_plot(), decompose_plot())
are wrapped in \donttest{} so each example file stays
within CRAN’s five-second budget. The first call of every example still
runs.CITATION.cff and the test artefact
Rplots.pdf are excluded from the build tarball, and the
test that produced Rplots.pdf draws to a null device
instead.legend_inside gates. The legend moves
inside the panel when a plot’s gate is satisfied, and the theme is left
alone when it is not.LICENSE file, and added
community and contribution files.First release. depictr is a unified, consistent toolkit of
publication-ready plots spanning the whole analysis workflow. It grew
out of, and generalises, three earlier plotting functions
(frequentist_bayesian_plot, plot.fixef.allFit
and powercurvePlot).
explore_distribution(),
explore_categorical(), explore_bivariate(),
explore_pairs(), correlation_heatmap(),
missingness_map(), outlier_plot(),
raincloud_plot(), group_comparison_plot(),
scatter_trend() and summary_table().estimation_plot() for estimation statistics: group
effect sizes (mean differences, Cohen’s d / Hedges’ g)
with bootstrap confidence intervals, in the spirit of the ‘new
statistics’.ecdf_plot() (empirical cumulative distribution,
optionally by group), ridgeline_plot() (overlapping
per-group densities) and dumbbell_plot() (a connected
two-group comparison across categories).explore_distribution() gains facet to draw
one panel per group instead of overlaying them (much clearer beyond a
few groups), and correlation_heatmap() gains
reorder to cluster correlated variables together.pca_plot() and scree_plot() (principal
component analysis), cluster_plot() (k-means on
principal-component axes) and dendrogram_plot()
(hierarchical clustering), and survival_plot()
(Kaplan-Meier curves with a number-at-risk table, median survival and an
optional log-rank test, all computed in base R).silhouette_plot() and k_diagnostic() help
choose and validate the number of clusters (silhouette widths, plus
elbow and average-silhouette diagnostics).timeseries_plot() (one or more series with an optional
moving average), acf_plot() (autocorrelation / partial
autocorrelation) and decompose_plot() (trend / seasonal /
remainder decomposition).seasonal_plot() (seasonal subseries) and
ts_forecast() (a simple, dependency-free forecast with
prediction intervals).tidy_estimates() provides the shared tidy estimate
table, with methods for lm, glm,
merMod and data frames and a fallback to
broom::tidy().coefficient_plot(), compare_models(),
frequentist_bayesian_plot(), effects_plot(),
interaction_plot(), random_effects_plot(),
optimizer_fixef_plot() and
model_fit_table().frequentist_bayesian_plot() now draws the full Bayesian
posterior for each term as a half-eye density and overlays the matching
frequentist point estimate and confidence interval, so the two
inferential frameworks can be compared directly. It reads posterior
draws from brmsfit, stanreg,
draws/matrix objects or a data frame.residual_diagnostics_plot(),
influence_plot(), qq_plot(),
vif_plot(), roc_curve_plot(),
pr_curve_plot(), gain_plot(),
lift_plot(), calibration_plot() and
confusion_matrix_plot().binned_residual_plot() (binned residuals for logistic
and other GLMs, with approximate error bounds) and
threshold_plot() (classification metrics across decision
thresholds, highlighting Youden’s J and the maximum-F1
cut-off).posterior_plot() summarises posterior draws with a
choice of styles ("halfeye", "interval",
"gradient" or "dots") and can annotate a
region of practical equivalence (ROPE) and the probability of
direction.power_curve_plot() for power-analysis curves (e.g. from
simr).theme_depictr(), depictr_palette(),
scale_colour_depictr() (and
scale_color_depictr(), scale_fill_depictr()),
palette_preview(), format_terms(),
model_report() (a one-figure model overview),
arrange_plots() and save_plot().depictr_options() sets package-wide defaults once,
covering the brand and accent colours, qualitative palette, base font
size and family, and the colour used for missing values. Every plot and
scale then honours them.coefficient_plot(), compare_models(),
posterior_plot() and
frequentist_bayesian_plot() gain a
facet/scales option that lays each term out in
its own free-scaled panel, so terms on very different scales (a large
intercept alongside small slopes) stay legible instead of being squished
onto the zero line. frequentist_bayesian_plot() uses this
layout by default.silhouette_plot() cluster labels no longer clip.
raincloud_plot() uses one colour per group across all
layers. dendrogram_plot() hides leaf labels for large
trees. confusion_matrix_plot() picks each label’s colour
from the tile luminance. gain_plot() and
lift_plot() label their reference lines.
timeseries_plot() shows a single legend, and
k_diagnostic() now returns the diagnostic curve as a
plot.coefficient_plot() gains standardise,
scaling each coefficient by its predictor’s standard deviation so
magnitudes are comparable. model_report() uses it by
default, removing the empty band in its coefficient panel.vif_plot() shows the ordinary VIF (not its square root)
for single-df terms, scales the axis to the data, and draws a single
clearly-labelled threshold line (reported in the caption when it is
off-axis), leaving no wide empty band or hard-to-read guides.seasonal_plot(style = "season") reverses its sequential
legend so the darkest, most-recent cycle sits at the top, matching the
plotted order.coefficient_plot(),
compare_models() and
frequentist_bayesian_plot(), where they are read from the
model, so conditionunrelated becomes condition
and word_frequency becomes word frequency.
optimizer_fixef_plot() and posterior_plot()
gain a labels argument for the same. Any user-supplied
labels take precedence. pca_plot() likewise
shows underscores in its loading-arrow labels as spaces
(soil_ph -> soil ph).silhouette_plot() (the bands are labelled in place) and
cluster_plot() when the centroids are labelled.survival_plot() has been tidied in several ways. The
log-rank annotation renders a proper chi-squared and an italic
p, formatted APA style (no leading zero, p < .001
below that threshold). The median guide is labelled
median <value>. The y-axis title margin is tighter,
and the colour legend and the number-at-risk table list the groups in
the same order, following the group factor’s levels.legend_inside argument (off by default) draws the
legend inside the panel, over a semi-transparent background, in a corner
the plot usually leaves empty, which reclaims the right-hand margin. It
is offered by roc_curve_plot(), gain_plot(),
lift_plot() (bottom-right / top-right of the curve),
ecdf_plot(), survival_plot(),
explore_distribution(), dumbbell_plot() and
missingness_map(). For any other plot the same is one
theme() call, and vignette("exploring-data")
shows how, alongside tidying legend titles.theme_depictr() now centres legend titles over their
keys, which reads more tidily than ggplot2’s default left alignment,
especially for an inside or a top/bottom legend.estimation_plot() reserves more headroom above the
lower panel so the effect-size annotation (Hedges’ g / Cohen’s
d) is never clipped.scree_plot() colour-matches and names its dual axes,
‘Variance explained (bars)’ on the left and ‘Cumulative (line)’ on the
right.model_report()’s n and R, and
estimation_plot()’s g / d.crop_yield
column is now fertiliser,
coefficient_plot()/model_report() take
standardise, and confusion_matrix_plot() takes
normalise.lexical_decision
(counterbalanced priming experiment), wellbeing_survey
(with realistic missingness), crop_yield (a
fertiliser-by-treatment field trial), clinical_trial
(right-censored survival with a rare adverse event) and
monthly_sales (two seasonal retail series).depictr_palette()
provides sequential and diverging variants.
palette_preview() can show any one, or all three, and can
simulate deuteranopia, protanopia or tritanopia so a palette’s
legibility can be checked directly.lme4, broom,
simr, survival, brms,
posterior, ggdist, cluster,
boot) are in Suggests and used only when
available, so the package installs and checks without them. Vignettes
draw on small precomputed model fits shipped in
inst/extdata/, so they knit without a Bayesian or
mixed-model toolchain.seed
(cluster_plot(), qq_plot() and
residual_diagnostics_plot()) restore the caller’s random
number generator state afterward, so passing one for reproducibility has
no side effect on your own subsequent random draws.