publiplots.barplot¶
- publiplots.barplot(data, x, y, hue=None, hatch=None, color=None, edgecolor=None, ax=None, title='', xlabel='', ylabel='', linewidth=None, capsize=None, alpha=None, border_radius=None, palette=None, hatch_map=None, legend=True, legend_kws=None, annotate=None, errorbar='se', gap=0.1, order=None, hue_order=None, hatch_order=None, multiple='dodge', stack_by=None, **kwargs)[source]¶
Create a publication-ready bar plot.
Aggregates long-form data by a categorical axis (
xory) and draws one bar per group, with optional color / hatch grouping and optional stacking. Under the hoodmultiple="dodge"(the default) wrapsseaborn.barplot()and applies publiplots’ palette, hatch, transparency, and legend-stash styling in a post-draw pass;multiple="stack"/"fill"bypasses seaborn (which has no stacked mode) and draws segments directly withax.bar/ax.barhat integer category positions with cumulativebottom=/left=.- Parameters:
data (DataFrame) – Input data in long form — one row per observation.
x (str) – Column names for the two axes. Exactly one must be categorical (category dtype, object, or string) and the other numeric.
xcategorical +ynumeric → vertical bars;ycategorical +xnumeric → horizontal bars. If neither column is categorical, raisesValueError.y (str) – Column names for the two axes. Exactly one must be categorical (category dtype, object, or string) and the other numeric.
xcategorical +ynumeric → vertical bars;ycategorical +xnumeric → horizontal bars. If neither column is categorical, raisesValueError.hue (str, optional) – Column name for color grouping. When distinct from the categorical axis, bars split within each category — side-by-side under
multiple="dodge", stacked undermultiple="stack"/"fill". When equal to the categorical axis, hue collapses to per-category coloring (no splitting).hatch (str, optional) –
Column name driving a second categorical dimension encoded via hatch textures — the texture-based analogue of
hue. Undermultiple="dodge": whenhatchis distinct from bothhueand the categorical axis, bars split along a second dodge dimension and the legend renders two entries (seehue-and-hatch double-split in the bar gallery). Undermultiple="stack"/"fill":hatchcan drive the stack on its own (leavehueunset) — useful for B&W-friendly stacks — or share the column withhue(hatch=hue) to pattern each stack segment by its hue level. When bothhueandhatchare distinct non-categorical columns, passstack_by="hue"orstack_by="hatch"to pick which dimension stacks; the other is dodged side-by-side within each category.Patterns are drawn from
publiplots.HATCH_PATTERNSby default; density is controlled globally viapubliplots.set_hatch_mode()("dense","sparse", or"off") or overridden per-plot withhatch_map. Callpubliplots.list_hatch_patterns()to see the catalog.color (str, optional) – Fixed color for all bars when no hue split is active. Accepts any matplotlib color string (
"#ff0000","red", etc.). Falls back torcParams["color"].edgecolor (str, optional) – Explicit edge color override. When
None(the default, also the default ofrcParams["edgecolor"]), the edge matches the face color — publiplots’ double-layer transparent-fill styling. Set to a specific color ("black") to draw bars with consistent outlines regardless of fill.ax (Axes, optional) – Matplotlib axes to draw on. If
None, creates a new figure viapubliplots.layout.subplots()so the publiplots layout manager can keep geometry stable. To control axes dimensions, pre-create withpp.subplots(axes_size=(w_mm, h_mm))and passax=.title (str or None, default="") – Plot title. Pass
Noneto leave the existing title unchanged.xlabel (str or None, default="") – Axis labels. Pass
Noneto leave the existing label unchanged.ylabel (str or None, default="") – Axis labels. Pass
Noneto leave the existing label unchanged.linewidth (float, optional) – Width of bar edges and hatch strokes. Defaults to
rcParams["lines.linewidth"].capsize (float, optional) – Width of errorbar caps in data units (dodge path only — stacked bars drop errorbars). Defaults to
rcParams["capsize"].alpha (float, optional) – Transparency of the bar fill (edges stay fully opaque).
0= outlined bars only;1= solid fill. Defaults torcParams["alpha"].border_radius (float or (top_mm, bottom_mm) tuple, optional) – Corner radius for the bars, in millimeters (print-consistent, independent of data-axis range). A scalar rounds all four corners symmetrically; a 2-tuple rounds the top and bottom independently, enabling infographic-style bars with rounded tops and flat baselines (
border_radius=(1.5, 0)). Defaults to thebar.border_radiusrcParam ((0, 0)= flat). Set globally viapp.rcParams['bar.border_radius'] = 1.5.palette (str, dict, or list, optional) –
Color palette. Can be:
str: seaborn palette name or publiplots palette namedict: explicit{hue_level: color}mappinglist: list of colors assigned in hue-level order
Only used when a hue split is active.
hatch_map (dict, optional) –
Mapping from hatch-column values to matplotlib hatch-pattern strings, overriding the per-
hatch_modedefaults. Matplotlib hatches interpret:/\|-+xoO.*; repeating a glyph increases density (e.g."///").Example (two-level hatch with a plain control group):
hatch_map={"control": "", "treated": "///"}publiplots.HATCH_PATTERNSlists the built-in patterns thehatch_moderesolver picks from; callpubliplots.list_hatch_patterns()to print them.legend (bool or dict, default=True) – Whether to stash & render the legend. Accepts
boolordict[kind, bool]for per-kind control (e.g.legend={"hatch": False}hides just the hatch entry in a double-split bar plot).Falsesuppresses stashing entirely, so a figure-levelpubliplots.legend()group won’t claim any entries from this axes.legend_kws (dict, optional) – Extra kwargs forwarded to the legend builder. Notable keys:
inside=Truewithloc=...places the legend inside the axes using matplotlib’s corner-based placement;hue_label/hatch_labeloverride the title shown above each entry.annotate (bool or dict, optional) –
If truthy, label each bar with its aggregated value. Pass a
dictto forward options topubliplots.annotate():fmt(Python format spec),anchor("outside"/"inside"/"top"/"left"/"right"),offset(mm),color,rotation(degrees).Under
multiple="stack"/"fill"the default anchor is"inside"and one label is produced per drawn segment; undermultiple="dodge"the default anchor is"outside"and one label is produced per bar.errorbar (str or None, default="se") – Error bar type for the dodge path:
"se"(standard error),"sd"(standard deviation),"ci"(confidence interval), tuple("pi", q)for percentile intervals, callable, orNonefor no error bars. Undermultiple="stack"/"fill"errorbars are always dropped with aUserWarning— per-segment errors are not additive without covariance info.gap (float, default=0.1) – Gap between adjacent bars, as a fraction of bar width. Under
"dodge"this is the gap between hue/hatch levels within a category; under"stack"/"fill"this is the gap between stacks across the categorical axis.order (list, optional) – Order of the categorical axis. Determines both draw order and the tick-label sequence.
hue_order (list, optional) – Explicit order of hue levels. Under
"stack"/"fill", also determines stack order bottom-to-top (first level at the base, last level on top) and the legend entry order.hatch_order (list, optional) – Order of hatch levels. Under
"stack"/"fill"withhatchdriving the stack, determines stack order bottom-to-top.multiple ({"dodge", "stack", "fill", "gain"}, default="dodge") –
How to arrange bars across the secondary (hue / hatch) categorical dimension within each category of the primary axis.
"dodge"(default): levels sit side-by-side within each category via seaborn’s dodging. Current behavior, unchanged — supports errorbars,hue + hatchdouble-split, and the full four-case legend dispatcher."stack": levels sit on top of each other within each category, each segment’s base set to the cumulative height (or width, horizontal) of the levels below. Drawn directly withax.bar/ax.barh— seaborn’s barplot has no stack mode."fill": stack and then normalize so every stack sums to 1.0 (100%-stacked bars — good for showing proportions whose totals differ across categories)."gain": pairwise comparison for exactly 2 levels. Per category: the bottom segment showsminof the two values (colored by the losing level); the top segment showsmax - min(colored by the winning level). Bar top = max. Who wins can flip across categories — the base color flips accordingly. Use for summary metrics that don’t compose by sum (AUC, accuracy, F1); for additive quantities use"stack". Ties render as a single bar in the first level’s color. Missing one of the two levels at some category raisesValueError.
Stacking requires at least one of
hue/hatchto be set and distinct from the categorical axis. If neither is set, raisesValueError. When both are distinct non-categorical columns, usestack_by=(below) to pick the stack dimension — the other is dodged side-by-side within each category.hue == hatch(both drive a single stack, patterns overlaid on colored swatches) is allowed.stack_by ({"hue", "hatch"}, optional) – Required when
multiple in {"stack", "fill"}and bothhueandhatchare distinct non-categorical columns. Picks which dimension accumulates along the value axis; the other dimension dodges side-by-side within each category (so each category showsN_otherdodged stacks, each ofN_stack_bysegments). Ignored when only one ofhue/hatchis active. PassNonein the single-dim case — the sole split dimension becomes the stack.**kwargs – Additional keyword arguments passed to
seaborn.barplot()in the dodge path. Ignored in the stack/fill path.figsizeis always rejected — usepp.subplots(axes_size=...)and passax=.
- Returns:
The axes where the plot was drawn. Recover the figure handle with
ax.get_figure().- Return type:
Axes
- Raises:
ValueError – If neither
xnoryis categorical; ifmultipleis not one of"dodge","stack","fill","gain"; ifmultiple="stack"|"fill"|"gain"is requested without a stack column (hue/hatch); ifmultiple="stack"|"fill"|"gain"is requested with bothhueandhatchset as distinct non-categorical columns but nostack_by=was provided; ifmultiple="gain"is requested with a stack column that has ≠ 2 levels or a level missing at some category.TypeError – If
figsizeis passed (publiplots owns figure geometry viapubliplots.subplots()).
- Warns:
UserWarning – If
errorbaris set undermultiple="stack"|"fill"; the errorbar is silently dropped (per-segment errors are not additive without covariance information).
Notes
Performance. The dodge path delegates aggregation to seaborn; the stack/fill path aggregates once in a single pass via the shared
publiplots.annotate._splits.BarSplitSpeciterator (the same deterministic draw order used for annotate pairing).Legend stash. Every call stashes
LegendEntryobjects on the axes (unlesslegend=False); per-axes legends render unless a figure-levelpubliplots.legend()group claims them.Examples
Simple bar plot:
>>> ax = pp.barplot(data=df, x="category", y="value")Color grouping via
hue:>>> ax = pp.barplot(data=df, x="time", y="value", ... hue="group", palette="pastel")
Two categorical dimensions via
hue+hatch(side-by-side):>>> ax = pp.barplot( ... data=df, x="cell_type", y="viability", ... hue="treatment", hatch="time", ... palette={"Vehicle": "#8E8EC1", "Drug": "#60a8a8"}, ... hatch_map={"24h": "", "48h": "///"}, ... )
Value labels on each bar:
>>> ax = pp.barplot(data=df, x="category", y="value", ... annotate={"fmt": ".2f"})
Stacked bars (
multiple="stack") with per-segment labels:>>> ax = pp.barplot( ... data=df, x="cohort", y="count", hue="stage", ... multiple="stack", errorbar=None, ... hue_order=["Early", "Mid", "Late"], ... annotate={"fmt": ".0f"}, ... )
100%-stacked proportions with percentage labels:
>>> ax = pp.barplot( ... data=df, x="cohort", y="count", hue="stage", ... multiple="fill", errorbar=None, ... annotate={"fmt": ".0%"}, ... )
B&W-friendly stack keyed by hatch (no hue):
>>> ax = pp.barplot( ... data=df, x="cohort", y="count", hatch="stage", ... multiple="stack", errorbar=None, color="#5D83C3", ... hatch_map={"Early": "", "Mid": "//", "Late": "xx"}, ... )
Horizontal stacked bars:
>>> ax = pp.barplot( ... data=df, x="count", y="cohort", hue="stage", ... multiple="stack", errorbar=None, ... )
Gain / improvement bars (pairwise comparison of 2 levels):
>>> ax = pp.barplot( ... data=df, x="metric", y="score", hue="model", ... multiple="gain", errorbar=None, ... palette={"Baseline": "#8E8EC1", "Proposed": "#60a8a8"}, ... annotate={"fmt": ".2f"}, ... )
Two categoricals: stack one, dodge the other (
stack_by):>>> ax = pp.barplot( ... data=df, x="cell_type", y="viability", ... hue="treatment", hatch="time", ... multiple="stack", stack_by="hue", errorbar=None, ... palette={"Vehicle": "#8E8EC1", "Drug": "#60a8a8"}, ... hatch_map={"24h": "", "48h": "///"}, ... )
See also
publiplots.histplotHistogram plot (also supports
multiple="stack"/"fill"via seaborn).publiplots.set_hatch_modeSet the global hatch-density mode.
publiplots.list_hatch_patternsPrint the built-in hatch patterns.
publiplots.annotateAdd value labels to bars (see
annotate=above for the subset promoted topp.barplot).publiplots.legendFigure-level legend group that claims stashed entries across multiple axes.