Skip to content

Releases: vega/altair

Weekly Build 5.6.0.dev20251103

03 Nov 03:27
0f79cd8

Choose a tag to compare

Pre-release

Weekly Pre-Release Build of Altair

This is a pre-release version for testing purposes.

Build Information

Version: 5.6.0.dev20251103
Tag: weekly-20251103-0f79cd8c
Previous Weekly Tag: weekly-20251027-d82683e5

Installation

From GitHub Repository (direct install)

Install directly from the tagged commit without downloading the wheel:

Command line (pip or uv):

pip install git+https://github.com/vega/altair.git@weekly-20251103-0f79cd8c
# or
uv pip install git+https://github.com/vega/altair.git@weekly-20251103-0f79cd8c

Add to pyproject.toml (pip/uv):

[project]
dependencies = [
    "altair @ git+https://github.com/vega/altair.git@weekly-20251103-0f79cd8c",
]

Add to pixi.toml (pixi):

[pypi-dependencies]
altair = { git = "https://github.com/vega/altair.git", rev = "weekly-20251103-0f79cd8c" }

From GitHub Release (manual download)

Download the wheel file from the assets below and install:

pip install altair-5.6.0.dev20251103-py3-none-any.whl

Testing & Feedback

Please note: This is a testing version. If you encounter any issues or unexpected behavior, we would greatly appreciate if you open an issue to report it. Your feedback helps improve Altair!

Weekly Build 5.6.0.dev20251027

27 Oct 03:29
d82683e

Choose a tag to compare

Pre-release

Weekly Pre-Release Build of Altair

This is a pre-release version for testing purposes.

Build Information

Version: 5.6.0.dev20251027
Tag: weekly-20251027-d82683e5
Previous Weekly Tag: None (first build)

Installation

From GitHub Repository (direct install)

Install directly from the tagged commit without downloading the wheel:

Command line (pip or uv):

pip install git+https://github.com/vega/altair.git@weekly-20251027-d82683e5
# or
uv pip install git+https://github.com/vega/altair.git@weekly-20251027-d82683e5

Add to pyproject.toml (pip/uv):

[project]
dependencies = [
    "altair @ git+https://github.com/vega/altair.git@weekly-20251027-d82683e5",
]

Add to pixi.toml (pixi):

[pypi-dependencies]
altair = { git = "https://github.com/vega/altair.git", rev = "weekly-20251027-d82683e5" }

From GitHub Release (manual download)

Download the wheel file from the assets below and install:

pip install altair-5.6.0.dev20251027-py3-none-any.whl

Testing & Feedback

Please note: This is a testing version. If you encounter any issues or unexpected behavior, we would greatly appreciate if you open an issue to report it. Your feedback helps improve Altair!

Version 5.5.0

24 Nov 00:12
b2ff8ce

Choose a tag to compare

Release 5.5.0

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 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.

Example of registering a custom theme

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")`

Example of instant feedback while you define a theme config through Pylance in VSCode

Enhancements

Olli Renderer

This release integrates the 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

Example of olli renderer:

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

Expressions and Selections

Several improvements were made to Altair's expression and selection APIs:

Example of combining predicates within .transform_filter

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

Example of using Python datetime.date for value in alt.selection_interval()

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

Multiple predicates and constraints in Chart.transform_filter

Example of using keyword-argument constraints to simplify filter compositions:

import altair as alt
from vega_datasets import data

source = data.population.url
chart = alt.Chart(source).mark_area().encode(
    x="age:O",
    y="sum(people):Q",
    color="year:O"
).transform_filter(year=2000, sex=1)
chart
image

Bug Fixes

Documentation

Several new examples were added to the documentation

Example of using alt.when().then().otherwise()

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

Example of using luminance in an expression to dynamically colorize text

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
Read more

Version 5.4.1

27 Aug 04:41

Choose a tag to compare

What's Changed

Enhancements

Bug Fixes

Documentation

Other Changes

Full Changelog: v5.4.0...v5.4.1

Version 5.4.0

11 Aug 08:22

Choose a tag to compare

What's Changed

Enhancements

Various typing improvements:

Bug Fixes

Documentation

Maintenance

New Contributors

Read more

Version 5.3.0

30 Mar 15:36

Choose a tag to compare

The Vega Project is happy to announce the release of version 5.3.0 of the Vega-Altair Python visualization library. This release has been 4 months in the making and includes enhancements, fixes, and documentation improvements from 11 contributors.

What's Changed

Enhancements

  • Add integration of VegaFusion and JupyterChart to enable scaling many interactive Vega-Altair charts to millions of rows. See VegaFusion Data Transformer for more information. Here is an example of histogram cross filtering with a 1 million row dataset.

    vegafusion_widget.mov
  • Add "browser" renderer to support displaying Vega-Altair charts in an external web browser. See Browser Renderer for more information (#3379).

    browser_renderer.mov
  • Support opening charts in the Vega editor with chart.open_editor() (#3358)

    open_editor.mov

Bug Fixes

  • Fix error when embed_options are None (#3376)
  • Fix type hints for libraries such as Polars where Altair uses the dataframe interchange protocol (#3297)
  • Fix anywidget deprecation warning (#3364)
  • Fix handling of Date32 columns in arrow tables and Polars DataFrames (#3377)

Backward-Incompatible Changes

  • Changed hash function from md5 to a truncated sha256 non-cryptograhic hash (#3291)
  • Updated chart.show() method to invoke the active renderer rather than depend on altair_saver (Which was never updated for use with Altair 5) (#3379).

New Contributors

Release notes by pull requests

Click to view all 44 PRs merged in this release
  • perf: Improve performance of Chart.from_dict by @RobinL in #3383
  • feature: Add browser renderer to open charts in external browser and update chart.show() to display chart by @jonmmease in #3379
  • fix: Don't error when embed_options are None by @jonmmease in #3376
  • fix: Handle Date32 columns in Arrow tables and Polars DataFrames by @jonmmease in #3377
  • fix: Support falling back to pandas when pyarrow is installed but too old by @jonmmease in #3387
  • docs: Remove release notes and fully capture them in GitHub Releases by @binste in #3380
  • Update save.py to use utf-8 instead of None per default by @franzhaas in #3278
  • Consolidate governance documents in Vega Organization by @domoritz in #3277
  • doc: histogram with gradient color by @mattijn in #3282
  • Update for FIPS Compliance by @ccravens in #3291
  • Docs: Fix link to project governance docs by @binste in #3298
  • Fix type checker errors for libraries such as Polars where Altair uses dataframe interchange protocol by @binste in #3297
  • Integrate VegaFusion into JupyterChart by @jonmmease in #3281
  • Add "jupyter" renderer based on JupyterChart by @jonmmease in #3283
  • Docs: Add section on displaying Altair charts in dashboards by @binste in #3299
  • Validate version of vegafusion-python-embed by @jonmmease in #3303
  • Add embed_options to JupyterChart and pass them through in "jupyter" renderer by @jonmmease in #3304
  • Add offline support to JupyterChart and "jupyter" renderer by @jonmmease in #3305
  • Type hints: Simplify to improve user experiences by @binste in #3307
  • Adding missing interpolation methods to Line example by @thomascamminady in #3323
  • Docs: Link to new section on Altair in Plotly docs by @binste in #3324
  • Docs: Mark completed items in roadmap by @binste in #3326
  • Docs: Mention Marimo in Dashboards section by @binste in #3334
  • Relax type hint for 'indent' in to_json method by @binste in #3342
  • MAINT: Reformat codebase with new style of ruff 0.3.0 by @binste in #3345
  • Docs: Add another version of the 'Multiline Tooltip' exmaple which uses the standard tooltip by @binste in #3340
  • Docs: Add privacy-friendly web analytics with plausible by @binste in #3346
  • Docs: Modifying scale of "multiple interactions" example and adding legend adjustments by @d-trigo in #3350
  • Add example of how to update titles based on a selection parameters by @joelostblom in #3353
  • Add all dependency group by @jonmmease in #3354
  • Add timeseries filtering example to illustrate subsetting of columns from selector values by @joelostblom in #3357
  • Fix anywidget deprecation warning by @jonmmease in #3364
  • Clarifications to the interactive docs by @joelostblom in #3362
  • Open charts in the default browser with open_editor method by @joelostblom in #3358
  • Change "mouse" to "pointer" everywhere by @joelostblom in #3363
  • doc: update numpy-tooltip-images.rst by @mattijn in #3233
  • Change a couple of more additional occurences of pointer over by @joelostblom in #3368
  • [Doc] Fix Chart and MarkDef language by @ChiaLingWeng in #3266
  • Add remaining changelog entries for 5.3 by @joelostblom in #3369
  • Upgrade to Vega-Lite 5.17.0 by @binste in #3367
  • Add a few 5.3 changelog entries by @jonmmease in #3372
  • Add note about conda "all" installation and how to install without optional dependencies by @joelostblom in #3373
  • Update README badges to reflect updated tool chain by @mattijn in #3374
  • chore: Add templates for PRs and automated release notes by @joelostblom in https://github.com/altair-vi...
Read more

Version 5.2.0

28 Nov 06:23

Choose a tag to compare

What's Changed

Enhancements

  1. Support offline HTML export using vl-convert (#3251)

    You now can use:

    chart.save('chart.html', inline=True)
    

    To create an HTML file with inline JavaScript dependencies. This enhancements takes advantage of HTML bundling support in vl-convert to replace the dependency on altair_viewer. Vega-Altair 5.2.0 expects vl-convert-python version 1.1.0 or higher for this enhancement.


  2. Support saving charts as PDF files using the vl-convert export engine (#3244)

    You now can use:

    chart.save('chart.pdf')
    

    To create an PDF representation of your chart. This enhancements takes advantage of PDF support in vl-convert to replace the dependency on altair_saver. Vega-Altair 5.2.0 expects vl-convert-python version 1.1.0 or higher for this enhancement.


  3. Support converting charts to sharable Vega editor URLs with chart.to_url() (#3252)

    You now can use:

    chart.to_url()
    

    To generate a Vega editor URL that opens the chart's specification in the online Vega editor. This enhancements takes advantage of lz-string URL-compatible compression in vl-convert. Vega-Altair 5.2.0 expects vl-convert-python version 1.1.0 or higher for this enhancement.

    Example:

    import altair as alt
    from vega_datasets import data
    
    chart = alt.Chart(data.cars.url).mark_point().encode(
        x='Horsepower:Q',
        y='Miles_per_Gallon:Q',
        color='Origin:N'
    )
    
    print(chart.to_url())

    https://vega.github.io/editor/#/url/vega-lite/N4Igxg9gdgZglgcxALlANzgUwO4tJKAFzigFcJSBnAdTgBNCALFAZgAY2AacaYsiygAlMiRoVYcAvpO50AhoTl4QpAE4AbFCDGEADpWQB6Q2DpQAdACtKdTOrhpV5qJkKGougLaG0mBHIBaeUVKV0oAATQARnMAJgBOczZDYLkTOVVKK0poEBkQTwyAa2VCAE9dTC1dCBJxfMwoSDoSJFQedQhVZXg7Oi0AeVVEEhBucsqtKAhPEjlNfIAPHqx1fuQQQS7QmuxMbvGKqo2AR1I5IjhFYl887jKVvq0AWTh1TEoAfUrVT4BxeadKBjEATY4gM4XYjXBxVaTcAAklDAjEwhS0On0Rh8fjk5gQV0YpAARuY4BBDMjUYUcf4AvZCJgfABWcxRABs5hY2VykiAA


  4. Pass format_locale and time_format_locale through to vl-convert to support locales in static image export (#3274)

    The preferred format of numbers, dates, and currencies varies by language and locale. Vega-Altair takes advantage of D3’s localization support to make it easy to configure the locale for your chart using the global alt.renderers.set_embed_options function. Vega-Altair 5.2.0 expects vl-convert-python version 1.1.0 or higher for this enhancement.

    See https://altair-viz.github.io/user_guide/customization.html#localization for more info (including the note with a caveat!).


  5. Vega-Altair is now a typed package, with type annotations for all public functions and classes and some of the internal code

    See #2951 for a full summary how we have implemented these. Type hints can help IDEs to provide a better development experience as well as static type checkers to catch potential errors before they appear at runtime.

Maintenance

  • Vega-Altair now uses ruff for maintaining code quality & consistency (#3243)
  • Vega-Altair is tested against Python 3.12 (#3235)

Bug Fixes

  • None

Backward-Incompatible Changes

  • None

New Contributors

Release Notes by Pull Request

Click to view all 31 PRs merged in this release

Full Changelog: v5.1.2...v5.2.0

Version 5.1.2

03 Oct 18:18

Choose a tag to compare

What's changed

Bug Fixes

  • Remove usage of deprecated Pandas parameter convert_dtypes by @binste in #3191
  • Fix encoding type inference for boolean columns when pyarrow is installed by @jonmmease in #3210

Full Changelog: v5.1.1...v5.1.2

Version 5.1.1

30 Aug 11:35

Choose a tag to compare

What's Changed

Full Changelog: v5.1.0...v5.1.1

Version 5.1.0

28 Aug 14:14

Choose a tag to compare

What's Changed

Enhancements

  1. The chart.transformed_data() method was added to extract transformed chart data

    For example when having an Altair chart including aggregations:

    import altair as alt
    from vega_datasets import data
    
    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

    image
    Its now possible to call the chart.transformed_data method to extract a pandas DataFrame containing the transformed data.

    chart.transformed_data()

    image
    This method is dependent on VegaFusion with the embed extras enabled.


  2. Introduction of a new data transformer named vegafusion

    VegaFusion is an external project that provides efficient Rust implementations of most of Altair's data transformations. Using VegaFusion as Data Transformer it can overcome the Altair MaxRowsError by performing data-intensive aggregations in Python and pruning unused columns from the source dataset.

    The data transformer can be enabled as such:

    import altair as alt
    alt.data_transformers.enable("vegafusion") # default is "default"
    DataTransformerRegistry.enable('vegafusion')

    And one can now visualize a very large DataFrame as histogram where the binning is done within VegaFusion:

    import pandas as pd
    import altair as alt
    
    # prepare dataframe with 1 million rows
    flights = pd.read_parquet(
        "https://vegafusion-datasets.s3.amazonaws.com/vega/flights_1m.parquet"
    )
    
    delay_hist = alt.Chart(flights).mark_bar(tooltip=True).encode(
        alt.X("delay", bin=alt.Bin(maxbins=30)),
        alt.Y("count()")
    )
    delay_hist

    image
    When the vegafusion data transformer is active, data transformations will be pre-evaluated when displaying, saving and converting charts as dictionary or JSON.

    See a detailed overview on the VegaFusion Data Transformer in the documentation.


  3. A JupyterChart class was added to support accessing params and selections from Python

    The JupyterChart class makes it possible to update charts after they have been displayed and access the state of interactions from Python.

    For example when having an Altair chart including a selection interval as brush:

    import altair as alt
    from vega_datasets import data
    
    source = data.cars()
    brush = alt.selection_interval(name="interval", value={"x": [80, 160], "y": [15, 30]})
    
    chart = alt.Chart(source).mark_point().encode(
        x='Horsepower:Q',
        y='Miles_per_Gallon:Q',
        color=alt.condition(brush, 'Cylinders:O', alt.value('grey')),
    ).add_params(brush)
    
    jchart = alt.JupyterChart(chart)
    jchart

    image
    It is now possible to return the defined interval selection within Python using the JupyterChart

    jchart.selections.interval.value
    {'Horsepower': [80, 160], 'Miles_per_Gallon': [15, 30]}

    The selection dictionary may be converted into a pandas query to filter the source DataFrame:

    filter = " and ".join([
        f"{v[0]} <= `{k}` <= {v[1]}"
        for k, v in jchart.selections.interval.value.items()
    ])
    source.query(filter)

    image
    Another possibility of the new JupyerChart class is to use IPyWidgets to control parameters in Altair. Here we use an ipywidget IntSlider to control the Altair parameter named cutoff.

    import pandas as pd
    import numpy as np
    from ipywidgets import IntSlider, link, VBox
    
    rand = np.random.RandomState(42)
    
    df = pd.DataFrame({
        'xval': range(100),
        'yval': rand.randn(100).cumsum()
    })
    
    cutoff = alt.param(name="cutoff", value=23)
    
    chart = alt.Chart(df).mark_point().encode(
        x='xval',
        y='yval',
        color=alt.condition(
            alt.datum.xval < cutoff,
            alt.value('red'), alt.value('blue')
        )
    ).add_params(
        cutoff
    )
    jchart = alt.JupyterChart(chart)
    
    slider = IntSlider(min=0, max=100, description='ipywidget')
    link((slider, "value"), (jchart.params, "cutoff"))
    
    VBox([slider, jchart])

    image
    The JupyterChart class is dependent on AnyWidget. See a detailed overview in the new documentation page on JupyterChart Interactivity.


  4. Support for field encoding inference for objects that support the DataFrame Interchange Protocol

    We are maturing support for objects build upon the DataFrame Interchange Protocol in Altair.
    Given the following pandas DataFrame with an ordered categorical column-type:

    import altair as alt
    from vega_datasets import data
    
    # Clean Title column
    movies = data.movies()
    movies["Title"] = movies["Title"].astype(str)
    
    # Convert MPAA rating to an ordered categorical
    rating = movies["MPAA_Rating"].astype("category")
    rating = rating.cat.reorder_categories(
        ['Open', 'G', 'PG', 'PG-13', 'R', 'NC-17', 'Not Rated']
    ).cat.as_ordered()
    movies["MPAA_Rating"] = rating
    
    # Build chart using pandas
    chart = alt.Chart(movies).mark_bar().encode(
        alt.X("MPAA_Rating"),
        alt.Y("count()")
    )
    chart

    image
    We can convert the DataFrame to a PyArrow Table and observe that the types are now equally infered when rendering the chart.

    import pyarrow as pa
    
    # Build chart using PyArrow
    chart = alt.Chart(pa.Table.from_pandas(movies)).mark_bar().encode(
        alt.X("MPAA_Rating"),
        alt.Y("count()")
    )
    chart

    image
    Vega-Altair support of the DataFrame Interchange Protocol is dependent on PyArrow.


  5. A new transform method transform_extent is available

    See the following example how this transform can be used:

    import pandas as pd
    import altair as alt
    
    df = pd.DataFrame(
        [
            {"a": "A", "b": 28},
            {"a": "B", "b": 55},
            {"a": "C", "b": 43},
            {"a": "D", "b": 91},
            {"a": "E", "b": 81},
            {"a": "F", "b": 53},
            {"a": "G", "b": 19},
            {"a": "H", "b": 87},
            {"a": "I", "b": 52},
        ]
    )
    
    base = alt.Chart(df, title="A Simple Bar Chart with Lines at Extents").transform_extent(
        extent="b", param="b_extent"
    )
    bars = base.mark_bar().encode(x="b", y="a")
    lower_extent_rule = base.mark_rule(stroke="firebrick").encode(
        x=alt.value(alt.expr("scale('x', b_extent[0])"))
    )
    upper_extent_rule = base.mark_rule(stroke="firebrick").encode(
        x=alt.value(alt.expr("scale('x', b_extent[1])"))
    )
    bars + lower_extent_rule + upper_extent_rule

    image


  6. It is now possible to add configurable pixels-per-inch (ppi) metadata to saved and displayed PNG images

    import altair as alt
    from vega_datasets import data
    
    source = data.cars()
    
    chart = alt.Chart(source).mark_boxplot(extent="min-max").encode(
        alt.X("Miles_per_Gallon:Q").scale(zero=False),
        alt.Y("Origin:N"),
    )
    chart.save("box.png", ppi=300)

    image

    alt.renderers.enable("png", ppi=144) # default ppi is 72
    chart

    image

Bug Fixes

  • Don't call len on DataFrame Interchange Protocol objects (#3111)

Maintenance

  • Add support for new referencing logic in version 4.18 of the jsonschema package

Backward-Incompatible Changes

  • Drop support for Python 3.7 which is end-of-life (#3100)
  • Hard dependencies: Increase minimum required pandas version to 0.25 (#3130)
  • Soft dependencies: Increase minimum required vl-convert-python version to 0.13.0 and increase minimum required vegafusion version to 1.4.0 (#3163, #3160)

New Contributors

Release Notes by Pull Request

Click to view all 52 PRs m...
Read more