Skip to main content

A native matplotlib backend for Altair

Project description

mpl-altair

A prototype native matplotlib backend for Altair. It renders Altair charts as real matplotlib Figure/Axes objects, not as an image copy of Vega-Lite's own renderer. That means a chart from mpl-altair is a genuine matplotlib plot: you can theme it with any mpl style, embed it in a subplot grid next to other matplotlib plots, or export it through any matplotlib backend (PDF, SVG, PGF/LaTeX, and so on).

Examples

Each pair shows the same Altair chart rendered by Vega-Lite's own renderer (left) and by mpl-altair (right). The goal is a semantic match, not a pixel match, so tick placement and label formatting differ where matplotlib's own conventions apply.

Altair (vl-convert) mpl-altair

Because the output is a real matplotlib figure, any matplotlib style restyles the whole chart. This is the same stacked bar converted with style="dark_background":

Quickstart

import altair as alt
import pandas as pd
import mplaltair

df = pd.DataFrame({"cat": ["a", "b", "c"], "val": [3, 7, 5]})
chart = alt.Chart(df).mark_bar().encode(x="cat:N", y="val:Q")

fig = mplaltair.convert(chart)
fig.savefig("bar.png")

convert() also accepts a raw Vega-Lite spec dict, an ax= to draw into (for embedding in a subplot grid), and a style= kwarg:

fig, (ax1, ax2) = plt.subplots(1, 2)
mplaltair.convert(chart1, ax=ax1)
mplaltair.convert(chart2, ax=ax2, style="dark_background")
  • style="vega-lite" (default): mpl-altair's bundled Vega-Lite-ish style sheet.
  • style=None or style="none": no style context is applied; the chart uses whatever mpl style/rcParams are already active in your session.
  • Anything else (style="dark_background", style="/path/to/my.mplstyle", ...): passed straight through to plt.style.context(...).

Using it as an Altair renderer

mpl-altair also registers itself as an Altair renderer, so chart objects display as matplotlib-rendered PNGs (for example, in a Jupyter notebook):

import mplaltair
mplaltair.enable()

chart  # displays as a matplotlib PNG instead of the default Vega-Lite renderer

How it works

Altair charts are specified in Vega-Lite, a high-level grammar of graphics. mpl-altair does not reimplement Vega-Lite's semantics. Instead it reuses the real Vega-Lite compiler and the real Vega dataflow engine to do all the hard work, and only translates the fully resolved result into matplotlib calls:

Altair chart (chart.to_dict())
  -> vl-convert: Vega-Lite spec -> Vega spec       (compiles all VL semantics/defaults)
  -> vegafusion: pre_transform_spec()               (evaluates transforms, inlines data)
  -> mpl-altair: reads the resolved scales/marks/axes/legends
  -> matplotlib calls, in data coordinates          (mpl owns axes, ticks, legends, layout)

This is why mpl-altair can support most standard Altair chart types without reimplementing Vega-Lite's scale, stacking, and binning logic from scratch: by the time mpl-altair sees the spec, vl-convert and vegafusion have already resolved it down to concrete rows, scale domains, and per-mark encodings. mpl-altair's job is just to walk that resolved structure and call the matching matplotlib function (ax.bar, ax.scatter, ax.plot, and so on).

Philosophy

matplotlib owns the axes, ticks, legends, and styling. mpl-altair does not chase pixel-for-pixel fidelity with Vega-Lite's own renderer.

Concretely:

  • Positions and data extents come from Vega-Lite's resolved scale domains, but tick placement, tick formatting, gridlines, and legend layout are matplotlib's own (AutoLocator, ConciseDateFormatter, ax.legend, fig.colorbar, and so on).
  • Colors follow matplotlib style, not Vega-Lite's rendering. A categorical color scale pulls from the active mpl prop_cycle; a continuous color scale pulls from rcParams['image.cmap']; Vega-Lite's compiled-in default mark color resolves to mpl's 'C0' so a plain, uncolored bar or point chart also restyles with the active mpl style.
  • The goal is a semantic match: same data extents, same categories, same stacking order, same legend content, same colors-per-series. Not a pixel match against Vega-Lite's SVG/canvas renderer.

If you want the classic Vega-Lite look, that's the default (mplaltair ships a vega-lite mpl style sheet, applied automatically). If you want your own house style, pass any matplotlib style name or your own style sheet, or use style=None to inherit whatever mpl style is already active in your session.

Supported

  • Marks: bar (simple, stacked, grouped), histogram (binned bar), point/circle/square (scatter), line (single and multi-series), area (stacked), tick, rule.
  • Layered charts (multiple marks sharing one set of scales), through the same code path as a single mark, with no extra handling needed.
  • Scales: linear, log, sqrt, time, band, point, ordinal/nominal.
  • Encodings: x, y, color (categorical -> mpl prop cycle, continuous -> colormap + colorbar), size (scatter), shape is not yet implemented.
  • Legends: categorical color/fill legends, continuous color colorbars, size legends (3-point proxy legend).
  • zero/nice domain flags, d3-style binning, temporal axes with mpl's ConciseDateFormatter.

Not supported (prototype scope)

  • geoshape, text, and arc marks.
  • Independently-resolved dual-axis charts (resolve_scale(y="independent")) -- not handled; each scale/mark is walked independently with no special detection, so results are undefined rather than validated or rejected.
  • Exact tick-format fidelity to Vega-Lite's d3-format strings (best-effort translation of trivial cases; mpl's own default formatting otherwise).

Unsupported or unrecognized spec shapes raise a warning and skip the offending piece rather than silently guessing or crashing the whole render. Larger missing pieces and known rendering issues are tracked on the issue tracker: faceting and concat (#1), interactivity and reactive signals (#2), and boundary gridline rendering (#3).

Gallery

scripts/gallery.py renders about a dozen representative charts through both mpl-altair and the reference vl-convert PNG renderer, side by side, into scripts/out/gallery.html, plus one extra row showing a chart re-themed with style="dark_background". Run it and open the HTML file in a browser:

MPLBACKEND=Agg uv run python scripts/gallery.py
open scripts/out/gallery.html

Tests

MPLBACKEND=Agg uv run pytest -q

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mpl_altair-0.1.0.tar.gz (42.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mpl_altair-0.1.0-py3-none-any.whl (47.9 kB view details)

Uploaded Python 3

File details

Details for the file mpl_altair-0.1.0.tar.gz.

File metadata

  • Download URL: mpl_altair-0.1.0.tar.gz
  • Upload date:
  • Size: 42.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.29 {"installer":{"name":"uv","version":"0.11.29","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for mpl_altair-0.1.0.tar.gz
Algorithm Hash digest
SHA256 481b2cd7ff3ed26ae31f09c21d3f57b53aee8f1c93ac79380fc6fc4b8471b837
MD5 614c140e6a3807c708e9bca37f5475f1
BLAKE2b-256 fc5221a9224bb1f2e58d1142d06b8964673c662cefee2497065f67cf814edf54

See more details on using hashes here.

File details

Details for the file mpl_altair-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: mpl_altair-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 47.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.29 {"installer":{"name":"uv","version":"0.11.29","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for mpl_altair-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 641740b1a5c80e103222e4df5ea0be267bebdedc1f5e9a2fc095211dd03f36c9
MD5 f95a503c81c7082de5ce58c404df232d
BLAKE2b-256 dccdab53ed47e5b805db79847a23b31a4642d587114f7c1ff37abea78d5ad815

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page