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
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~~ edit: this is now also supported in Dash and Shiny). 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))