I almost have it, but the filter selection only works when executing the cell in jupyter. It doesn't get updated when the dropdown selector is used. I have three parts:
df
's column Island
.selection_interval
that is connected to the scatterplot.df
is rendered below the scatterplot and the records shown in the table are dynamically presented based on the brush selection.It almost work perfectly, but the dropdown menu doesn't get updated for the scatterplot, BUT DOES get updated for the table. What am I missing here? I need the dropdown to filter out the chart too. Below is the code and the animated gif
import panel as pn
import pandas as pd
import altair as alt
pn.extension('vega', template='fast-list')
penguins_url = "https://raw.githubusercontent.com/vega/vega/master/docs/data/penguins.json"
df = pd.read_json(penguins_url)
brush = alt.selection_interval(name='brush') # selection of type "interval"
island = pn.widgets.Select(name='Island', options=df.Island.unique().tolist())
chart = alt.Chart(df.query(f'Island == "{island.value}"')).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=700,
height=200
).add_selection(brush)
vega_pane = pn.pane.Vega(chart, debounce=5)
def filtered_table(selection, island):
if not selection:
return '## No selection'
query = ' & '.join(
f'{crange[0]:.3f} <= `{col}` <= {crange[1]:.3f} & Island == "{island}"'
for col, crange in selection.items()
)
return pn.Column(
f'Query: {query}',
pn.pane.DataFrame(df.query(query).query(f'Island == "{island}"'), width=600, height=300)
)
pn.Column(
pn.Row(island, vega_pane),
pn.bind(filtered_table, selection = vega_pane.selection.param.brush, island=island))[![enter image description here][1]][1]
There are a few examples of how to achieve this in https://github.com/holoviz/panel/issues/4487, e.g.:
def filter_table(data, 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(data.query(query), width=600, height=300)
)
penguins_url = "https://raw.githubusercontent.com/vega/vega/master/docs/data/penguins.json"
df = pd.read_json(penguins_url)
island_dropdown = pn.widgets.Select(options=df['Island'].unique().tolist(), width=300)
dynamic_data = pn.bind(lambda island: df.loc[df['Island'] == island], island_dropdown)
brush = alt.selection_interval(name='brush') # selection of type "interval"
chart = alt.Chart(dynamic_data()).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'))
).add_params(
brush
)
altair_pane = pn.pane.Vega(chart)
def update_chart(_):
altair_pane.object = chart.properties(data=dynamic_data())
island_dropdown.param.watch(update_chart, 'value')
pn.Column(
island_dropdown,
pn.Row(
altair_pane,
pn.bind(filter_table, dynamic_data, altair_pane.selection.param.brush)
)
)