Skip to content

Get started

This guide works through a short analysis with depictr, from a first look at the data to a fitted model and its diagnostics. Every function returns a plotnine object, so anything shown here can be refined further with the usual + syntax.

Install

The first command below installs the core (plotnine, pandas, numpy, matplotlib and scipy), and the second adds the optional computation back-ends. The double quotes keep zsh, the default shell on macOS, from reading the brackets as a filename pattern.

pip install depictr
pip install "depictr[all]"

The exploratory, theme and accessibility tools work with the core install, and so do the model and time-series plots: they delegate to statsmodels, which plotnine itself requires. The classification and survival plots delegate to scikit-learn and lifelines, each an optional extra (depictr[classification], depictr[survival]). The gains, lift and calibration curves are computed by depictr itself and need neither. The depictr[models] extra remains to pin the tested statsmodels floor.

The idea

The whole workflow gets one theme, one colourblind-safe palette (the Okabe-Ito set) and one calling convention. Specialist computations stay with the packages that do them well, and each result is redrawn under the shared theme, so a ROC curve, a coefficient plot and a survival curve read as parts of one figure set.

import depictr as dp

Each call returns a plotnine object. In a Jupyter notebook it renders on display. In a script, call .show(), or save it with dp.save_plot(p, "fig.png").

A first look at the data

depictr ships the R package's synthetic datasets. Here is a lexical-decision experiment with reaction times in two priming conditions.

ld = dp.lexical_decision()
dp.explore_distribution(ld, "RT", group="condition", kind="density",
                        legend_inside=True)

The legend sits inside the panel, in the corner the distribution leaves empty. For a wider survey, a correlation heatmap and a missing-data map give a quick overview:

wb = dp.wellbeing_survey()
dp.correlation_heatmap(wb)
dp.missingness_map(wb, legend_inside=True)

Fitting and reading a model

depictr does not fit models. It reads a model you have fitted, or a tidy table of estimates. Fit an ordinary least-squares model with statsmodels, then read it from several angles.

import statsmodels.formula.api as smf

cy = dp.crop_yield()
# Q() quotes "yield" because it is a Python keyword.
model = smf.ols('Q("yield") ~ fertiliser + rainfall + soil_ph + treatment',
                cy).fit()

dp.coefficient_plot(model, title="Drivers of crop yield")
dp.effects_plot(model, "fertiliser")
dp.residual_diagnostics_plot(model)

The forest labels each term for a reader. The treatment row reads treatment: enhanced, the contrast of enhanced fields with the reference level, standard, and soil_ph reads soil ph. labels renames any term, labels="raw" keeps the model's own names, and format_terms applies the same rules to any list of names.

coefficient_plot also accepts a plain data frame of estimates (with columns term, estimate, conf_low, conf_high), so estimates from any source (a Bayesian fit, a bootstrap, a table copied from a paper) plot the same way. tidy_estimates is the shared converter that produces that standard table from any fitted model, and every model-family plot accepts either the model or that table.

dp.tidy_estimates(model)

Survival and classification

These families delegate to lifelines and scikit-learn. Kaplan-Meier curves with confidence limits, a log-rank test and a number-at-risk table are one call:

ct = dp.clinical_trial()
dp.survival_plot(ct["time"], ct["event"], group=ct["arm"],
                 risk_table=True, legend_inside=True, logrank=True)
dp.roc_curve_plot(ct["adverse_event"], ct["biomarker"])

Checking the accessibility claim

The default palette is the Okabe-Ito set, and the claim behind that choice is testable. A simulator of colour-vision deficiency, based on the model of Machado, Oliveira and Fernandes (2009), and a CIE-Lab distance test measure how far apart the palette's colours stay under each form of deficiency.

dp.palette_safety()
# {'min_delta_e': ..., 'safe': True, 'by_condition': {...}, ...}

A safe palette is not a safe figure, though, so check_figure audits a finished plot. It measures how separable the encoding colours are under each dichromacy and in greyscale, how small the text becomes at the width the figure will be printed at, how well text and geometry contrast with their backgrounds under WCAG, and whether any distinction rests on colour alone. Each row reports the value it measured beside the threshold, so a verdict can be argued with.

dp.check_figure(dp.explore_distribution(ld, "RT", group="condition"),
                width_cm=8.9)

The gallery's accessibility page renders both reports in full, and states the one limitation worth knowing: the colourblind-safety guarantee covers hue confusion alone, and two of the palette's colours print as the same grey.

Extending and composing

Because every function returns a plotnine object, the grammar-of-graphics extensions apply:

from plotnine import labs

dp.roc_curve_plot(
    ct["adverse_event"], ct["biomarker"]
) + labs(title="Adverse event")

To place several plots in one figure, use arrange_plots. It tags the panels A, B and so on, as the R function does, and tag_levels=None leaves them untagged:

dp.arrange_plots(dp.qq_plot(model), dp.influence_plot(model), ncol=2)

theme_depictr, scale_colour_depictr and depictr_palette style your own plots too, so a figure depictr did not draw still matches the set:

from plotnine import ggplot, aes, geom_point

(ggplot(cy, aes("fertiliser", "yield", colour="treatment"))
 + geom_point(alpha=0.7)
 + dp.scale_colour_depictr()
 + dp.theme_depictr())

For a journal that names a font, dp.theme_depictr(base_family="Arial") sets it on one plot. plotnine's own option sets it on every plot drawn afterwards, depictr's included, as depictr_options(base_family = ) does in R:

import plotnine

plotnine.options.base_family = "Arial"

Where next

The gallery renders a worked example from every family, and the API reference documents each function and its options.