The Vega-Altair team is pleased to announce the release of version 5.5.0. This version introduces several exciting new features and enhancements including a revamped theme system, a new renderer optimized for screen readers, and numerous type system updates that improve auto-completion and make it easier to integrate Altair into larger typed programs.
This release adds Python 3.13 and removes Python 3.8 support. It also includes a variety of documentation improvements and a range of important bug fixes.
Thanks to our maintainers (binste, dangotbanned, joelostblom, mattijn, and jonmmease), returning contributors (MarcoGorelli, daylinmorgan, and dsmedia), and first time contributors (jpn--, davidgroves, and apoorvkh) for these improvements.
What's Changed
Deprecation
alt.themes
This release deprecates the `alt.themes` `ThemeRegistry` object and replaces it with an improved theme API in the new `alt.theme` module. See the updated [Chart Themes](https://altair-viz.github.io/user_guide/customization.html#chart-themes) documentation for more information:
> [!NOTE]
> Usage of the legacy `alt.themes` registry will be supported until version 6, but will now display a warning on first use.
* Refactor `alt.themes` -> `alt.theme` by dangotbanned in [3618](https://github.com/vega/altair/pull/3618)
* Adds `register_theme` decorator by dangotbanned in [3526](https://github.com/vega/altair/pull/3526)
* Adds `ThemeConfig` (`TypedDict`) by dangotbanned in [3536](https://github.com/vega/altair/pull/3536)
Example of registering a custom theme
python
import altair as alt
import pandas as pd
data = pd.DataFrame({'x': [5, 3, 6, 7, 2],
'y': ['A', 'B', 'C', 'D', 'E']})
alt.theme.register("my_little_theme", enable=True)
def custom_theme():
return alt.theme.ThemeConfig(
config={
"bar":{"color":"black"}
}
)
chart = alt.Chart(data).mark_bar().encode(
x='x',
y='y',
)
chart enable default using `alt.theme.enable("default")`
<img src="https://hackmd.io/_uploads/rJ2miY1XJl.png" width="200">
Example of instant feedback while you define a theme config through Pylance in VSCode
<img src="https://hackmd.io/_uploads/SJ8Qi917Jx.gif" width="450">
Enhancements
Olli Renderer
This release integrates the [Olli](https://vis.csail.mit.edu/pubs/olli/) project to provide a chart renderer that augments chart visualizations with a keyboard-navigable structure accessible to screen readers.
* Add 'olli' renderer to generate accessible text structures for screen reader users by binste in [3580](https://github.com/vega/altair/pull/3580)
Example of `olli` renderer:
python
import altair as alt
from vega_datasets import data
alt.renderers.enable("olli")
cars = data.cars.url
chart = alt.Chart(cars).mark_bar().encode(
y='Cylinders:O',
x='mean_acc:Q'
).transform_aggregate(
mean_acc='mean(Acceleration)',
groupby=["Cylinders"]
)
chart
<img src="https://hackmd.io/_uploads/H1Cr9dJ7kl.png" width="555">
Expressions and Selections
Several improvements were made to Altair's [expression](https://altair-viz.github.io/user_guide/interactions/expressions.html) and [selection](https://altair-viz.github.io/user_guide/interactions.html#selections-capturing-chart-interactions) APIs:
* Generate `expr` method signatures, docs by dangotbanned in [3600](https://github.com/vega/altair/pull/3600)
* Support `&`, `|`, `~` on all `...Predicate` classes by dangotbanned in [3668](https://github.com/vega/altair/pull/3668)
* Support `datetime.(date|datetime)` in `Expression`(s) by dangotbanned in [3654](https://github.com/vega/altair/pull/3654)
* Support `datetime.(date|datetime)` as a `SchemaBase` parameter by dangotbanned in [3653](https://github.com/vega/altair/pull/3653)
* Add missing `float` to `IntoExpression` alias by dangotbanned in [3611](https://github.com/vega/altair/pull/3611)
Example of combining predicates within `.transform_filter`
python
import altair as alt
from vega_datasets import data
source = data.population.url
chart = alt.Chart(source).mark_line().encode(
x="age:O",
y="sum(people):Q",
color="year:O"
).transform_filter(
~alt.FieldRangePredicate(field='year', range=[1900, 1960])
& (alt.datum.age <= 70)
)
chart
<img src="https://hackmd.io/_uploads/B1e5TuJQyx.png" width="350">
Example of using Python `datetime.date` for `value` in `alt.selection_interval()`
python
import datetime
import altair as alt
from vega_datasets import data
source = data.unemployment_across_industries.url
dt_values = [datetime.date(2005, 1, 1), datetime.date(2009, 1, 1)]
brush = alt.selection_interval(
encodings=['x'],
value={"x": dt_values}
)
base = alt.Chart(source).mark_area(
color='goldenrod',
opacity=0.3
).encode(
x='yearmonth(date):T',
y='sum(count):Q',
)
background = base.add_params(brush)
selected = base.transform_filter(brush).mark_area(color='goldenrod')
background + selected
<img src="https://hackmd.io/_uploads/Sy29et1XJl.png" width="350">
Multiple `predicates` and `constraints` in `Chart.transform_filter`
* Support `Chart.transform_filter(*predicates, **constraints)` by dangotbanned in [3664](https://github.com/vega/altair/pull/3664)
Example of using keyword-argument `constraints` to simplify filter compositions:
python
import altair as alt
from vega_datasets import data
source = data.population.url
chart = alt.Chart(source).mark_line().encode(
x="age:O",
y="sum(people):Q",
color="year:O"
).transform_filter(year=2000, sex=1)
chart
<img src="https://hackmd.io/_uploads/rJvgGtkXJx.png" width="400">
Bug Fixes
* Resolve multiple `utils.use_signature` issues by dangotbanned in [3565](https://github.com/vega/altair/pull/3565)
* Relax `dict` annotations in `channels.py` by dangotbanned in [3573](https://github.com/vega/altair/pull/3573)
* Set charset=UTF-8 in HTML templates. by davidgroves in [3604](https://github.com/vega/altair/pull/3604)
* Replace unsafe `locals()` manipulation in `Chart.encode` by dangotbanned in [3637](https://github.com/vega/altair/pull/3637)
* Revise generated annotation order by dangotbanned in [3655](https://github.com/vega/altair/pull/3655)
* Resolve `alt.binding` signature/docstring issues by dangotbanned in [3671](https://github.com/vega/altair/pull/3671)
* Add missing `skip_requires_pyarrow(requires_tzdata=True)` by dangotbanned in [3674](https://github.com/vega/altair/pull/3674)
* Don't materialise Ibis table to PyArrow if using vegafusion data transformer by MarcoGorelli in [3566](https://github.com/vega/altair/pull/3566)
* `mypy` 1.12.0 errors by dangotbanned in [3632](https://github.com/vega/altair/pull/3632)
* Resolve warnings in `test_api.py` by dangotbanned in [3592](https://github.com/vega/altair/pull/3592)
Documentation
Several new examples were added to the documentation
Example of using `alt.when().then().otherwise()`
python
import altair as alt
from vega_datasets import data
source = data.cars()
brush = alt.selection_interval()
chart = alt.Chart(source).mark_point().encode(
x='Horsepower',
y='Miles_per_Gallon',
color=alt.when(brush).then("Origin").otherwise(alt.value("lightgray"))
).add_params(
brush
)
chart
<img src="https://hackmd.io/_uploads/BJA2tFk7kx.png" width="350">
Example of using luminance in an expression to dynamically colorize text
python
import altair as alt
from vega_datasets import data
source = data.barley()
base = alt.Chart(source).encode(
x=alt.X('sum(yield):Q').stack('zero'),
y=alt.Y('site:O').sort('-x'),
text=alt.Text('sum(yield):Q', format='.0f')
)
bars = base.mark_bar(
tooltip=alt.expr("luminance(scale('color', datum.sum_yield))")
).encode(
color='sum(yield):Q'
)
text = base.mark_text(
align='right',
dx=-3,
color=alt.expr("luminance(scale('color', datum.sum_yield)) > 0.5 ? 'black' : 'white'")
)
bars + text
<img src="https://hackmd.io/_uploads/r1-ydtkXJg.png" width="300">
* Unstack area to render cumulative chart correctly by joelostblom in [3558](https://github.com/vega/altair/pull/3558)
* Change remote nick to `origin` and capitalize version commit by joelostblom in [3559](https://github.com/vega/altair/pull/3559)
* Update releasing notes to reflect that main branch is now protected by binste in [3562](https://github.com/vega/altair/pull/3562)
* Split interactive docs section into subpages by joelostblom in [3561](https://github.com/vega/altair/pull/3561)
* Update docs to use correct init value for `selection_point` by jpn-- in [3584](https://github.com/vega/altair/pull/3584)
* Add example with overlapping bars in a grouped bar chart by mattijn in [3612](https://github.com/vega/altair/pull/3612)
* Bar chart with labels coloured by measured luminance by mattijn in [3614](https://github.com/vega/altair/pull/3614)
* Adds example Calculate Residuals by dangotbanned in [3625](https://github.com/vega/altair/pull/3625)
* Adds Vega-Altair Theme Test by dangotbanned in [3630](https://github.com/vega/altair/pull/3630)
* adds info with step size/independent scale by daylinmorgan in [3644](https://github.com/vega/altair/pull/3644)
* Fix "Layered chart with Dual-Axis" (Method syntax) by dangotbanned in [3660](https://github.com/vega/altair/pull/3660)
* Fix inaccurate `selection_interval` signature by dangotbanned in [3662](https://github.com/vega/altair/pull/3662)
* Update `selection_point` signature by dangotbanned in [3663](https://github.com/vega/altair/pull/3663)
* Update "Ranged Dot Plot" example by dangotbanned in [3665](https://github.com/vega/altair/pull/3665)
* Promote `when-then-otherwise` in User Guide by dangotbanned in [3544](https://github.com/vega/altair/pull/3544)
* Add initial date range to interval selection example by dsmedia in [3667](https://github.com/vega/altair/pull/3667)
* Generate docstrings for `mark_` methods by dangotbanned in [3675](https://github.com/vega/altair/pull/3675)
* Make plausible web analytics public and add link to maintainer notes by binste in [3571](https://github.com/vega/altair/pull/3571)
* Reduce `SchemaValidationError` traceback length by dangotbanned in [3530](https://github.com/vega/altair/pull/3530)
Maintenance
* Drop support for Python 3.8 by dangotbanned in [3647](https://github.com/vega/altair/pull/3647)
* Add support Python 3.13 by dangotbanned in [3591](https://github.com/vega/altair/pull/3591)
* Improve `Then` annotations, autocompletion, docs by dangotbanned in [3567](https://github.com/vega/altair/pull/3567)
* Resolve `SIM910` lint in `display.py` by dangotbanned in [3613](https://github.com/vega/altair/pull/3613)
* Add `typings/` to `.gitignore` by dangotbanned in [3560](https://github.com/vega/altair/pull/3560)
* Adds `test-(slow|fast)` options by dangotbanned in [3555](https://github.com/vega/altair/pull/3555)
* Remove `channels` parameter in `infer_encoding_types` by dangotbanned in [3564](https://github.com/vega/altair/pull/3564)
* Add include patterns for `pyright` by dangotbanned in [3583](https://github.com/vega/altair/pull/3583)
* Fix support `pylance>=2024.9.1` by dangotbanned in [3585](https://github.com/vega/altair/pull/3585)
* Bump `typing_extensions` python to `3.14` by dangotbanned in [3593](https://github.com/vega/altair/pull/3593)
* Future-proof Duration type error message test by MarcoGorelli in [3606](https://github.com/vega/altair/pull/3606)
* Use `breaking`, `deprecation` labels in changelog by dangotbanned in [3623](https://github.com/vega/altair/pull/3623)
* Bump `vl-convert-python` to `1.7.0` by dangotbanned in [3633](https://github.com/vega/altair/pull/3633)
* Add upper version bound on VegaFusion by jonmmease in [3638](https://github.com/vega/altair/pull/3638)
* Add untyped `vegafusion` to `mypy` overrides by dangotbanned in [3640](https://github.com/vega/altair/pull/3640)
* Remove outdated `schemapi` comment by dangotbanned in [3641](https://github.com/vega/altair/pull/3641)
* Support generating `Union` aliases by dangotbanned in [3656](https://github.com/vega/altair/pull/3656)
* Moved `vl-convert-python` to `save` dependency group by apoorvkh in [3609](https://github.com/vega/altair/pull/3609)
* Simplify `channels.py` overloads by dangotbanned in [3659](https://github.com/vega/altair/pull/3659)
* Use more robust dtype comparisons, use Narwhals stable API in tests by MarcoGorelli in [3670](https://github.com/vega/altair/pull/3670)
* Use duckdb instead of ibis to test interchange-only support by MarcoGorelli in [3672](https://github.com/vega/altair/pull/3672)
* Resolve or ignore `pyright`-only warnings by dangotbanned in [3676](https://github.com/vega/altair/pull/3676)
* Add `pyarrow-stubs` to `dev` dependencies by dangotbanned in [3679](https://github.com/vega/altair/pull/3679)
* Prep for VegaFusion 2.0 by jonmmease in [3680](https://github.com/vega/altair/pull/3680)
* Replace unconditional `typing_extensions` imports by dangotbanned in [3683](https://github.com/vega/altair/pull/3683)
* VegaFusion 2 will support narwhals by jonmmease in [3682](https://github.com/vega/altair/pull/3682)
* Bump narwhals to v1.13.1 by mattijn in [3690](https://github.com/vega/altair/pull/3690)
* Distinct Olli renderer template by mattijn in [3689](https://github.com/vega/altair/pull/3689)
* Fix ci warning for pivot.rst by mattijn in [3691](https://github.com/vega/altair/pull/3691)
* Correct nested `expr` equivalence by dangotbanned in [3624](https://github.com/vega/altair/pull/3624)
**Full Changelog**: https://github.com/vega/altair/compare/v5.4.1...v5.5.0