Workaround for externally emitting signals/events from interactions with VegaLite/Altair plots?

Viewed 493

To my understanding, there is no official support for emitting signals/events from interactions in VegaLite/Altair, such as selecting points in a scatter plot, other than to charts in the same view/composition.

Is there currently any workaround for this that would capture which points are selected in a scatter plot and process them outside VegaLite ("outside" = in Python for me as I am using Altair)?

For example, could I make a selection persistent and saved to a json spec that I could parse in Python? Or could I write a custom javascript function that is triggerd by a chart selection and saved as a Python variable or printed to some stream that I could read from Python?

Example code from the docs for a chart with an interactive selection:

import altair as alt
from vega_datasets import data

brush = alt.selection_interval() 
chart = alt.Chart(data.cars.url).mark_point().encode(
    x='Horsepower:Q',
    y='Displacement:Q',
    color=alt.condition(brush, 'Origin:N', alt.value('lightgray')),
    tooltip='Horsepower:Q').add_selection(brush)
chart
3 Answers

Hmm, I too am interested in this so I went searching in the Altair docs.

what if you did:

from pprint import pprint
pprint(chart.to_dict())

Here is what I get:

{'$schema': 'https://vega.github.io/schema/vega-lite/v4.8.1.json',
 'config': {'view': {'continuousHeight': 300, 'continuousWidth': 400}},
 'data': {'url': 'https://vega.github.io/vega-datasets/data/cars.json'},
 'encoding': {'color': {'condition': {'field': 'Origin',
                                      'selection': 'selector001',
                                      'type': 'nominal'},
                        'value': 'lightgray'},
              'tooltip': {'field': 'Horsepower', 'type': 'quantitative'},
              'x': {'field': 'Horsepower', 'type': 'quantitative'},
              'y': {'field': 'Displacement', 'type': 'quantitative'}},
 'mark': 'point',
 'selection': {'selector001': {'type': 'interval'}}}

That must be part of it? maybe?

The capability to listen to Vega events and define custom callback for e.g. selected points was recently merged in Panel and is included in the 0.13 release! This is the only Python dashboarding package that supports custom callbacks on selections in Altair charts. Here is an example from the docs:

penguins_url = "https://raw.githubusercontent.com/vega/vega/master/docs/data/penguins.json"
brush = alt.selection_interval(name='brush')  # selection of type "interval"

chart = alt.Chart(penguins_url).mark_point().encode(
    x=alt.X('Beak Length (mm):Q', scale=alt.Scale(zero=False)),
    y=alt.Y('Beak Depth (mm):Q', scale=alt.Scale(zero=False)),
    color=alt.condition(brush, 'Species:N', alt.value('lightgray'))
).properties(
    width=250,
    height=250
).add_selection(
    brush
)

vega_pane = pn.pane.Vega(chart, debounce=10)

vega_pane

df = pd.read_json(penguins_url)

def filtered_table(selection):
    if not selection:
        return '## No selection'
    query = ' & '.join(
        f'{crange[0]:.3f} <= `{col}` <= {crange[1]:.3f}'
        for col, crange in selection.items()
    )
    return pn.Column(
        f'Query: {query}',
        pn.pane.DataFrame(df.query(query), width=600, height=300)
    )

pn.Row(vega_pane, pn.bind(filtered_table, vega_pane.selection.param.brush))

image

Related