Displaying Altair Charts

Altair produces Vega-Lite visualizations, which require a Javascript frontend to display the charts. Because notebook environments combine a Python backend with a Javascript frontend, many users find them convenient for using Altair.

Altair charts work out-of-the-box on Jupyter Notebook, JupyterLab, Zeppelin, and related notebook environments, so long as there is a web connection to load the required javascript libraries.

Altair can also be used with various IDEs that are enabled to display Altair charts, and can be used offline in most platforms with an appropriate frontend extension enabled; details are below.

Altair’s Renderer Framework

Because different display systems have different requirements and constraints, Altair provides an API to switch between various renderers to tune Altair’s chart representation. These can be chosen with the renderer registry in alt.renderers. Some of the built-in renderers are:

alt.renderers.enable('html')

(the default) Output an HTML representation of the chart. The HTML renderer works in JupyterLab, Jupyter Notebook, Zeppelin, and many related notebook frontends, as well as Jupyter ecosystem tools like nbviewer and nbconvert HTML output. It requires a web connection in order to load relevant Javascript libraries.

alt.renderers.enable('mimetype')

(default prior to Altair 4.0): Output a vega-lite specific mimetype that can be interpreted by appropriate frontend extensions to display charts. This also outputs a PNG representation of the plot, which is useful to view plots offline or on platforms that don’t support rendering vegaspecs, such as GitHub. It works with newer versions of JupyterLab, nteract, and VSCode-Python, but does not work with the Jupyter Notebook, or with tools like nbviewer and nbconvert.

Other renderers can be installed by third-party packages via Python’s entrypoints system; see Renderer API.

Displaying in JupyterLab

JupyterLab 1.0 and later will work with Altair’s default renderer with a live web connection: no render enable step is required.

Optionally, for offline rendering in JupyterLab, you can use the mimetype renderer:

# Optional in JupyterLab: requires an up-to-date vega labextension.
alt.renderers.enable('mimetype')

and ensure you have the proper version of the vega labextension installed; for Altair 4 this can be installed with:

$ jupyter labextension install @jupyterlab/vega5-extension

In JupyterLab version 2.0 or newer, this extension is installed by default, though the version available in the jupyterlab release often takes a few months to catch up with new Altair releases.

Displaying in the Jupyter Notebook

The classic Jupyter Notebook will work with Altair’s default renderer with a live web connection: no render enable step is required.

Optionally, for offline rendering in Jupyter Notebook, you can use the notebook renderer:

# Optional in Jupyter Notebook: requires an up-to-date vega nbextension.
alt.renderers.enable('notebook')

This renderer is provided by the ipyvega notebook extension. which can be installed and enabled either using pip:

$ pip install vega

or conda:

$ conda install vega --channel conda-forge

In older versions of the notebook (<5.3) you need to additionally enable the extension:

$ jupyter nbextension install --sys-prefix --py vega

Displaying in nteract

nteract cannot display HTML outputs natively, and so Altair’s default html renderer will not work. However, nteract natively includes vega and vega-lite mimetype-based rendering. To use Altair in nteract, ensure you are using a version that supports the vega-lite v4 mimetype, and use:

alt.renderers.enable('mimetype')

Displaying in VSCode

VSCode-Python includes a vega-lite renderer to display charts in-app via the vega-lite mimetype output. You can enable it by running:

alt.renderers.enable('mimetype')

Working in non-Notebook Environments

The Vega-Lite specifications produced by Altair can be produced in any Python environment, but to render these specifications currently requires a javascript engine. For this reason, Altair works most seamlessly with the browser-based environments mentioned above.

If you would like to render plots from another Python interface that does not have a built-in javascript engine, you’ll need to somehow connect your charts to a second tool that can execute javascript.

There are a few options available for this:

Vega-enabled IDEs

Some IDEs have extensions that natively recognize and display Altair charts. Examples are:

  • The VSCode-Python extension, which supports native Altair and Vega-Lite chart display as of November 2019.

  • The Hydrogen project, which is built on nteract and renders Altair charts via the mimetype renderer.

Altair Viewer

For non-notebook IDEs, a useful companion is the Altair Viewer package, which provides an Altair renderer that works directly from any Python terminal. Start by installing the package:

$ pip install altair_viewer

When enabled, this will serve charts via a local HTTP server and automatically open a browser window in which to view them, with subsequent charts displayed in the same window.

If you are using an IPython-compatible terminal altair_viewer can be enabled via Altair’s standard renderer framework:

import altair as alt
alt.renderers.enable('altair_viewer')

If you prefer to manually trigger chart display, you can use the built-in Chart.show() method to manually trigger chart display:

import altair as alt

# load a simple dataset as a pandas DataFrame
from vega_datasets import data
cars = data.cars()

chart = alt.Chart(cars).mark_point().encode(
    x='Horsepower',
    y='Miles_per_Gallon',
    color='Origin',
).interactive()

chart.show()

This command will block the Python interpreter until the browser window containing the chart is closed.

Manual save() and display

If you would prefer, you can manually save your chart as html and open it with a web browser. Once you have created your chart, run:

chart.save('filename.html')

and use a web browser to open this file.

Renderer API

If you want to enable Altair rendering with behavior not provided by the built-in renderers, you can use the renderer API to create that custom behavior. In Altair, a renderer is any function that accepts a Vega-Lite or Vega visualization specification as a Python dict, and returns a Python dict in Jupyter’s MIME Bundle format. The keys of the MIME bundle should be MIME types (such as image/png) and the values should be the data for that MIME type (text, base64 encoded binary or JSON). The type signature of a renderer is thus:

def renderer(spec: dict) -> dict:
    ...

Altair’s default html rendeer returns a cross-platform HTML representation using the "text/html" mimetype; schematically it looks like this:

def default_renderer(spec):
    bundle = {'text/html': generate_html(spec)}
    metadata = {}
    return bundle, metadata

Propertly-configured Jupyter frontends know how to interpret and display charts using custom vega-specific mimetypes; for example:

  • Vega-Lite 4.x: application/vnd.vegalite.v4+json

  • Vega 5.x: application/vnd.vega.v5+json

Altair’s mimetype renderer uses this mechanism to return the spec directly:

def default_renderer(spec):
    bundle = {}
    metadata = {}
    bundle['text/plain'] = '<VegaLite 4 object>`
    bundle['application/vnd.vegalite.v4+json'] = spec
    return bundle, metadata

If a renderer needs to do custom display logic that doesn’t use Jupyter’s display system, it can return an empty MIME bundle dict:

def non_jupyter_renderer(spec):
    # Custom display logic that uses the spec
    ...
    # Return empty MIME bundle
    return {}

Altair offers an API to list the known renderers, register new ones and enable a given one. To return the registered renderers as a Python list:

>>> import altair as alt
>>> alt.renderers.names()
['colab', 'default', 'html', 'json', 'jupyterlab', 'kaggle', 'mimetype',
'nteract', 'png', 'svg', 'zeppelin']

To enable the JSON renderer, which results in a collapsible JSON tree view in JupyterLab/nteract:

>>> alt.renderers.enable('json')

To register and enable a new renderer:

>>> alt.renderers.register('custom_renderer', custom_renderer)
>>> alt.renderers.enable('custom_renderer')

Renderers can also be registered using the entrypoints API of Python packages. For an example, see ipyvega.