I am using Altair to generate my plots (As i need the linked bar-chart selection) and Panel to create my dashboard. I have two dropdowns, where the values in the second are conditional on the value in the first.
When I use a Single Select dropdown the dashboard works as expected. However when I try and use any Mulitiple select widget I get no data rendered on my chart. See code below. Testdataset available here:https://github.com/KWSpittles/testdata
import panel as pn
import altair as alt
import pandas as pd
from vega_datasets import data
import datetime as dt
from altair import datum
alt.renderers.enable('default')
pn.extension('vega')
data = pd.read_excel('randomtestdata.xlsx')
df = pd.DataFrame(data, columns=['Parent Location','Location','Alert Definition','Alert Type','Initiated Date'])
df = df[(df['Parent Location'] == 'Zone 1') | (df['Parent Location'] == 'Zone 2' )| (df['Parent Location'] == 'Zone 3' )]
df.rename(columns={'Parent Location': 'ParentLocation'},
inplace=True, errors='raise')
source = df
title = '##Dashboard'
subtitle = 'This is a test dashboard. Use widgets below to show desired chart.'
_locations = {
'Zone 1': source.loc[source['ParentLocation'] == 'Zone 1']['Location'].unique().tolist(),
'Zone 2' : source.loc[source['ParentLocation'] == 'Zone 2']['Location'].unique().tolist(),
'Zone 3': source.loc[source['ParentLocation'] == 'Zone 3']['Location'].unique().tolist()
}
zone = pn.widgets.Select(
name = 'Select a Zone',
value ='Zone 1',
options =['Zone 1', 'Zone 2', 'Zone 3']
)
#The following does not work
location = pn.widgets.MultiSelect(
name = 'Select a Location',
value =[True],
options =_locations[zone.value]
)
# The following does works:
# location = pn.widgets.Select(
# name = 'Select a Location',
# value = _locations[zone.value][0],
# options =_locations[zone.value]
# )
date_range_slider = pn.widgets.DateRangeSlider(
name='Date range to consider',
start=dt.datetime(2021, 1, 1), end=dt.datetime(2022, 1, 1),
value=(dt.datetime(2021, 1, 1), dt.datetime(2022, 1, 1))
)
@pn.depends(zone.param.value, location.param.value, date_range_slider.param.value, watch=True)
def get_plot(zone, location, date_range): # start function
df = source
df['Initiated Date'] = pd.to_datetime(df['Initiated Date']) # format date as datetime
start_date = date_range_slider.value[0]
end_date = date_range_slider.value[1]
mask = (df['Initiated Date'] > start_date) & (df['Initiated Date'] <= end_date)
df = df.loc[mask]
selection2 = alt.selection_single(fields=['Alert Type'])
chart = alt.Chart(df).mark_bar(
color="#0c1944",
opacity=0.8).encode(
x=alt.X('Alert Type:O', scale=alt.Scale(domain=source['Alert Type'].unique())),
y='count(Alert Type)').transform_filter(
(datum.Location == location)
).add_selection(selection2)
chart2 = alt.Chart(df).mark_bar(
color="#0c1944",
opacity=0.8).encode(
x='Alert Definition',
y='count(Alert Definition)').transform_filter(
(datum.Location == location)
).transform_filter(selection2)
return (chart|chart2)
@pn.depends(zone.param.value, watch=True)
def _update_locations(zone):
locations = _locations[zone]
location.options = locations
location.value = locations[0]
return
pn.Row(
pn.Column(title, subtitle, zone, location, date_range_slider,
get_plot )
)