Skip to content

BrokenAxes: a grid class for discontinuous axis ranges #3923

@AdityaAsopa

Description

@AdityaAsopa

This proposes a BrokenAxes class alongside a broken_axes() figure-level function, following the same pattern as JointGrid / jointplot and FacetGrid.

The problem

Datasets with structural outliers — where a small number of values sit far outside the main distribution — force an unpleasant choice on a single continuous axis: crop the outliers, distort the scale, or compress everything else into an illegible band. The conventional fix is to manually stack two subplots and hide spines, suppress tick labels, and draw break markers by hand. It requires ~30 lines of per-figure boilerplate with no reusable API.

This comes up consistently across domains: health expenditure, GDP per capita, military spending, seismic data, genomics. It's the most frequently requested chart type that seaborn has no answer for.

Proposed API


# Y-axis break — seaborn.load_dataset("healthexp") natural test case
g = sns.BrokenAxes(ylims=[(0, 7500), (9000, 12500)], height_ratios=[4, 1])
g.plot(sns.lineplot, data=healthexp, x="Year", y="Spending_USD", hue="Country")
g.set_axis_labels("Year", "Health Spending (USD)")

# X-axis break
g = sns.BrokenAxes(xlims=[(1970, 1985), (2005, 2020)])

# Three segments
g = sns.BrokenAxes(ylims=[(0, 2000), (3500, 7500), (9000, 12500)])

# Embed inside a larger figure layout — see note below
fig = plt.figure(figsize=(12, 4))
gs = gridspec.GridSpec(1, 2, figure=fig)
g = sns.BrokenAxes(ylims=[(0, 7500), (9000, 12500)], subplot_spec=gs[0, 0])
ax = fig.add_subplot(gs[0, 1])

Relation to existing issues

This is also related to #2830 (figure reuse in FacetGrid) and #3917 (embedding JointGrid in a subfigure). The subplot_spec= parameter uses GridSpecFromSubplotSpec to embed the broken-axis layout inside an existing figure cell — a general solution to the figure-ownership limitation those issues describe.

Implementation

A working implementation exists on a fork: AdityaAsopa/seaborn, branch feature/broken-axes.

  • Inherits from _BaseGrid; follows the JointGrid class structure
  • Layout built entirely on GridSpec / GridSpecFromSubplotSpec — no hacks
  • Break markers use the official matplotlib custom-marker technique for consistent angle across segment sizes
  • Marker color and weight read from axes.edgecolor / axes.linewidth rcParams
  • 46 tests; no regressions in the existing 121 axisgrid tests
  • Docstring notebook (13 examples), tutorial section added to axis_grids.ipynb, whatsnew entry

Happy to open a PR if this direction is of interest, or to adjust the design based on feedback.

Image Image Image

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions