I am writing a dash plotly python code that draws a stack barchart for each county’s sanitation indicators like below.
However, I cannot seem to find the correct way to ensure the stacked bar chart increments the counties on the x axis based on the dropdown values ie. if I select 5 values in the dropdown, the stack barchart should show 5 stacked barcharts for each county (eg. Baringo, Kisumu, Mombasa, Nairobi, Nyeri). Likewise, if I narrow down the counties in the dropdown to just 2, the plotly graph should show just two stacked bars for each county (eg. Bomet, Kiambu).
All the files used on the code are available in this github repository, but the name of the python file is stack_barchart.py
. The code in the aformentioned .py
file is as below:
# Import the necessary packages
import pandas as pd
import plotly.express as px
from dash import Dash, dash_table, dcc, html, Input, Output
df = pd.read_csv('sanitation_long2.csv')
df2 = pd.read_csv('human_waste_filtered.csv')
df2 = df2[['County', 'Conventional Households', 'Main Sewer', 'Septic tank', 'Cess pool', 'VIP Latrine',
'Pit latrine covered', 'Pit Latrine uncovered', 'Bucket latrine', 'Open/ Bush', 'Bio-septic tank/ Biodigester', 'Not Stated']]
# Initialize the app
app = Dash(__name__)
server = app.server
# App layout
app.layout = html.Div([
html.H2(children="Pie chart showing human waste disposal as proportion of conventional households (Kenya 2019 census)"),
# Create dropdown
dcc.Dropdown([name for name in df.County], id='selected_county', multi=True),
# Create stack bar graph/chart
dcc.Graph(figure={}, id='controls-and-graph'),
# Create filterable datatable
dash_table.DataTable(columns= [
{'name': i, 'id': i} for i in df2.columns
],
data=df2.to_dict('records'),
filter_action='native',
sort_action='native',
page_size=5),
# Create download button
html.Div([
html.Button("Download CSV", id='btn-csv'),
dcc.Download(id='download-dataframe-csv')
])
])
@app.callback(
Output('controls-and-graph', 'figure'),
Input('selected_county', 'value'),
)
def update_graph(dropdown_choices):
dff = df[df.County == dropdown_choices]
fig = px.bar(dff, x='County', y='value', color='indicator')
return fig
# Function to show and download dataframe
@app.callback(
Output('download-dataframe-csv', 'data'),
Input('btn-csv', 'n-clicks'),
prevent_initial_call=True
)
def func(n_clicks):
return dcc.send_data_frame(df2.to_csv, 'mydf.csv')
if __name__ == '__main__':
app.run_server(debug=True)
I tried playing around with the def update_graph()
code block values, including following the callback examples from here. However, they only made the problem more complex and incomprehensible. The persistent error that popped up in most tries was:
ValueError: ('Lengths must match to compare', (470,), (1,))
Googling the problem only brought one solution which referenced a medium article. However, I couldn’t seem to understand the logic of the solution.
Could someone help me have a stack bar chart plotly graph that upscales and downscales county name and their indicators based on the multi-value dropdown? For more info on dash plotly dropdowns, see this page.