publiplots.subplots¶
- publiplots.subplots(nrows=1, ncols=1, *, axes_size=None, width_ratios=None, height_ratios=None, sharex=False, sharey=False, title_space=None, xlabel_space=None, ylabel_space=None, right=None, hspace=None, wspace=None, outer_pad=None, label_outer=True, **fig_kw)[source]¶
Create a figure and a grid of axes with deterministic axes dimensions.
publiplots’ flagship 0.10 layout API. Every axes in the grid has exactly
axes_sizemillimeters as its spine bounding box — this is the inviolate quantity. The figure canvas is sized to fit the grid plus auto-measured decorations (titles, axis labels, tick labels), which are remeasured on first draw. Any per-side reservation passed explicitly is locked and never remeasured.This is the opposite mental model from
matplotlib.pyplot.subplots(), which fixes the figure and lets axes shrink. When comparing to matplotlib/seaborn code, note thataxes_sizeis in mm (not inches) andfigsize=is rejected — publiplots owns the figure geometry. Seereject_figsize()for the rationale.- Parameters:
nrows (int, default 1) – Grid shape (must be >= 1).
ncols (int, default 1) – Grid shape (must be >= 1).
axes_size ((float, float) or float, in mm, optional) – Declared per-cell axes bounding box, in millimeters. A scalar is coerced to
(s, s). IfNone, falls back topp.rcParams["subplots.axes_size"]— the baseline publication default is(70, 50)mm. This is the per-cell budget; total grid-width budget isaxes_size[0] * ncolsand total grid- height budget isaxes_size[1] * nrows. Asymmetric grids (seewidth_ratios/height_ratios) renormalize that budget across columns/rows without changing the total.width_ratios (sequence of float, optional) – Per-column width weights, matching
matplotlib.pyplot.subplots()in spirit. Length must equalncols. Derived mm widths areratios[c] / sum(ratios) * (axes_size[0] * ncols)— so the total grid-width budget is preserved and each cell’s width is its ratio-share of that budget. Equal ratios recover the uniform-grid behavior. Use for JointGrid-style layouts (e.g.,width_ratios=[7, 2]for a big main panel + thin right marginal).height_ratios (sequence of float, optional) – Per-row height weights. Same semantics as
width_ratiosbut along the row axis.sharex (bool or {"all", "row", "col", "none"}, default False) – Axis-sharing semantics, matching
matplotlib.pyplot.subplots().sharey (bool or {"all", "row", "col", "none"}, default False) – Axis-sharing semantics, matching
matplotlib.pyplot.subplots().title_space (float | sequence, optional) –
Per-cell reservations, in millimeters. Accepts:
None(default) — usepp.rcParams["subplots.<name>"]as the initial value and auto-measure every position on first draw.A float — broadcast across the whole side AND lock it; no position is auto-measured.
A sequence of length
nrows(fortitle_space/xlabel_space) orncols(forylabel_space/right). Each element is either a float (lock that position) orNone(leave it auto-measured, initial value from rcParams). Mixed sequences such as(0.0, None)let you pin one row/column while the other auto-grows — this is howpp.JointGridclamps the inside-facing joint↔marginal edges to 0 mm without disabling label auto-measurement on the outer edges.
xlabel_space (float | sequence, optional) –
Per-cell reservations, in millimeters. Accepts:
None(default) — usepp.rcParams["subplots.<name>"]as the initial value and auto-measure every position on first draw.A float — broadcast across the whole side AND lock it; no position is auto-measured.
A sequence of length
nrows(fortitle_space/xlabel_space) orncols(forylabel_space/right). Each element is either a float (lock that position) orNone(leave it auto-measured, initial value from rcParams). Mixed sequences such as(0.0, None)let you pin one row/column while the other auto-grows — this is howpp.JointGridclamps the inside-facing joint↔marginal edges to 0 mm without disabling label auto-measurement on the outer edges.
ylabel_space (float | sequence, optional) –
Per-cell reservations, in millimeters. Accepts:
None(default) — usepp.rcParams["subplots.<name>"]as the initial value and auto-measure every position on first draw.A float — broadcast across the whole side AND lock it; no position is auto-measured.
A sequence of length
nrows(fortitle_space/xlabel_space) orncols(forylabel_space/right). Each element is either a float (lock that position) orNone(leave it auto-measured, initial value from rcParams). Mixed sequences such as(0.0, None)let you pin one row/column while the other auto-grows — this is howpp.JointGridclamps the inside-facing joint↔marginal edges to 0 mm without disabling label auto-measurement on the outer edges.
right (float | sequence, optional) –
Per-cell reservations, in millimeters. Accepts:
None(default) — usepp.rcParams["subplots.<name>"]as the initial value and auto-measure every position on first draw.A float — broadcast across the whole side AND lock it; no position is auto-measured.
A sequence of length
nrows(fortitle_space/xlabel_space) orncols(forylabel_space/right). Each element is either a float (lock that position) orNone(leave it auto-measured, initial value from rcParams). Mixed sequences such as(0.0, None)let you pin one row/column while the other auto-grows — this is howpp.JointGridclamps the inside-facing joint↔marginal edges to 0 mm without disabling label auto-measurement on the outer edges.
hspace (float, optional) – Gaps between rows/cols and outer margin, in millimeters.
Nonefalls back topp.rcParams["subplots.<name>"]. These are never auto-measured.wspace (float, optional) – Gaps between rows/cols and outer margin, in millimeters.
Nonefalls back topp.rcParams["subplots.<name>"]. These are never auto-measured.outer_pad (float, optional) – Gaps between rows/cols and outer margin, in millimeters.
Nonefalls back topp.rcParams["subplots.<name>"]. These are never auto-measured.**fig_kw – Forwarded to
matplotlib.pyplot.figure().figsize=is rejected (seereject_figsize()); matplotlib layout-engine kwargs (layout,constrained_layout,tight_layout) are ignored with aUserWarning.label_outer (bool or {"all"}, default True) – When
Trueandsharex/shareyis active, hide interior tick labels, offset text, and axis labels — leaving labels only on the bottom row (x) and left column (y), matching seaborn’sFacetGrid.Falseor"all"draws every label (the pre-0.x behavior). With no sharing,Trueis a no-op. Seepubliplots.label_outer()to re-apply this after lateset_xlabel/set_ylabelcalls.
- Returns:
fig (matplotlib.figure.Figure) – The created figure.
axes (matplotlib.axes.Axes or numpy.ndarray of Axes) – Shape matches
matplotlib.pyplot.subplots()withsqueeze=True.
Notes
Auto-growing canvas. The figure starts at the size computed from
axes_sizeplus initial rcParams reservations. On first draw, decorations (titles, axis labels, tick labels) are measured and the reservations for unlocked sides are expanded to fit. The axes bbox itself never changes — only the canvas around it grows.Legend overhangs. If you attach a
publiplots.legend()band withside="right"/"bottom"/"left"/"top", the extra space for the legend is auto-computed on first draw from the rendered group’s width/height. There is nolegend_columnkwarg to set by hand.Examples
Single axes (defaults):
>>> import publiplots as pp >>> fig, ax = pp.subplots() >>> pp.barplot(data=df, x='category', y='value', ax=ax)
Explicit mm axes size:
>>> fig, ax = pp.subplots(axes_size=(80, 50)) # 80 mm x 50 mmGrid of axes with row-shared y-axis:
>>> fig, axes = pp.subplots(2, 3, axes_size=(40, 30), sharey='row')Locked title reservation (no auto-measurement for this side):
>>> fig, ax = pp.subplots(axes_size=(60, 40), title_space=8)Asymmetric 2×2 grid — a JointGrid-shaped layout with a large main panel and thin marginal strips.
axes_sizesets the per-cell budget thatwidth_ratios/height_ratiosrenormalize:>>> fig, axes = pp.subplots(2, 2, axes_size=(45, 35), ... width_ratios=[7, 2], height_ratios=[2, 5])
With
axes_size=(45, 35)andncols=2the total grid-width budget is 90 mm; the ratio[7, 2]splits it into70and20mm. Same for rows: total 70 mm →20and50mm.See also
publiplots.label_outerHide interior labels on an existing shared grid.
reject_figsizeGuard used by plot functions to reject
figsize=.publiplots.rcParamsWhere the
subplots.*defaults live.