Black Lives Matter. Please consider donating to Black Girls Code today.

Callback not working

Hi I am new to using Dash and I am having some trouble with using app callbacks. I have created an app that I want to display a timeseries graph with date on the x-axis and Y as a measures count called total jobs. I am grabbing this data from an elasticsearch database. I am filtering this dataset by county so basically for a specific county what would be the total jobs over a time period. I am using this county dropdown as an input for the output graph. However my update_graph function does not seem to work and I am not able to generate or update the graph based on my dropdown value. I have attached my code below. Any help would be much appreciated. Let me know if you need more info?

# -*- coding: utf-8 -*-
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
from elasticsearch import Elasticsearch
from elasticsearch_dsl import *
import plotly.graph_objs as go
import pandas as pd

es = Elasticsearch([{'host': 'localhost', 'port': 9200}])
res = es.search(index="paindex", body={"query": {"match_all": {}}})
data=pd.DataFrame(res["hits"]["hits"][0]["_source"]["data"])
data["date"]=pd.to_datetime(data['date'])
data= data.groupby(["county", "date"]).sum()
data.reset_index(inplace=True)
data=data.sort_values('date')

counties= data['county'].unique()

app = dash.Dash()

app.layout = html.Div([

   html.H1("Data Detective"),

   html.Div([
   html.Label('County'),
   dcc.Dropdown(
       id='County',
       options=[{'label': i, 'value': i} for i in counties],
       value=['Philadelphia'],
       multi=True
   ),

   html.Label('Measure'),
   dcc.Dropdown(
       id='Measure',
       options=[
           { 'label': 'Jobs', 'value': 'Jobs'},
           {'label': 'Schools', 'value': 'Schools'}
       ],
       value=['Jobs', 'Schools'],
       multi=True
   )]),

   dcc.Graph(
       id='Time-series-graph',
       figure = {
       'data' : [go.Scatter(
                 x= data.date[data['county'] == county],
                 y= data.total_jobs[data['county'] == county],
                 name= county) for county in data['county'].unique()],
       'layout' : go.Layout(
       xaxis = {
           'title' : 'Date',
       },
       yaxis = {
           'title' : 'Total Jobs'
       })
   }
)])

@app.callback(
   dash.dependencies.Output('Time-series-graph', 'figure'),
   [dash.dependencies.Input('County', 'value')])
def update_graph(County):
   plot= data[data['county'] == County]
   return {
       'data' : [go.Scatter(
                 x= plot.date[plot['county'] == County]['Value'],
                 y= plot.total_jobs[plot['county'] == County]['Value'],
                 name= County)],
       'layout' : go.Layout(
       xaxis = {
           'title' : 'Date',
       },
       yaxis = {
           'title' : 'Total Jobs'
       })
       }



if __name__ == '__main__':
   app.run_server(debug=True)

Hm, not sure exactly what is going wrong here, but one thing that I notice is that you have multi=True but then you are filtering in update_graph with data[data['county'] == County]. If multi=True, then the input arguments to update_graph is going to be a list of strings, not just a single string.
My guess is that this pandas filtering (data[data['county'] == County]) isn’t working with the list value. I’d try changing multi=False in your dropdowns first. Once that works, you can handle the multiple-strings case.

1 Like

@chriddyp Hey Thanks yes I ended up turning multi=True to False and it works with a single drop down. Just curious if I want to have a multi-drop down and plot a line for each county that is selected in the drop down from the dataset what would the best method be? I am curious to see your thoughts? Should I first write code that splits the strings up and then have code that takes each strings and returns a line graph?
Thanks for all your help so far.