Dash Dropdown input changing multiple graphs - Pandas/Plotly/Dash

Hello everyone!

I am trying to build a dashboard using dash and plotly, but I am having trouble with my callbacks. I have reviewed the documentation but can’t seem to get things to work correctly. The layout that I have is correct, I just cannot get the graphs to update. The idea is that when a job number is selected, all the graphs will change accordingly. The data is mostly qualitative, so I have used pandas to create dataframes for each graph.

When I run the code in a seperate jupyter notebook the graphs work perfectly, just not in the script and app. I am new to python and dash so I apologize if the mistake is something silly.

The intended structure of the dashboard is as follows:
— Row1 — Header
— Row2 — 2 columns with Dropdown Selectors in each (rowid_selector & solution_selector)
— Row3 — 2 columns with 2 graphs (histograms)
— Row4 — 2 columns with 2 graphs (linechart & pie)
— Row5 — Customer Intent dataframe

Here is the code that I have written so far:

from dash import dash, dcc, html, dash_table
from dash.dependencies import Input, Output, State
import dash_bootstrap_components as dbc
import plotly.express as px
import plotly.graph_objects as go
import pandas as pd
import numpy as np

df = pd.read_csv('data2.csv')
cdata = pd.read_csv('cdata.csv')

app = dash.Dash(external_stylesheets=[dbc.themes.MINTY])
server = app.server

rowid_options = []
for rowid in df['rowID'].unique():
    rowid_options.append({'label':rowid,'value':rowid})

solution_options = []
for solution in df['solution'].unique():
    solution_options.append({'label':solution,'value':solution})

app.layout = dbc.Container([
    dbc.Row([html.H1("Analytics Dashboard")]),
    dbc.Row([
        html.Label("Select the campaign RowID or Solution that you would like to query from the dropdowns below."),
        dbc.Col([dcc.Dropdown(id = "rowid_selector", options = rowid_options,
        clearable=True, placeholder="Select your RowID")
    ]),
        dbc.Col([dcc.Dropdown(id = "solution_selector", options = solution_options,
        clearable=True, placeholder="Select your Product/Solution")
    ])]),
    dbc.Row([
        dbc.Col([dcc.Graph(
            id='graph1', figure={}
            )
            ]),
        dbc.Col([dcc.Graph(
            id='graph2', figure={}
            )
            ]),
    ]),
    dbc.Row([
        dbc.Col([dcc.Graph(
            id='graph3', figure={}
            )
            ]),
        dbc.Col([dcc.Graph(
            id='graph4', figure={}
            )
            ])
    ]),
        dbc.Row([html.H2("Customer Intent Tracker")]),
        dbc.Row([
            html.Div([
                dash_table.DataTable(
                    id='datatable-interactivity',
                    columns=[{"name": i, "id": i, "deletable": False, "selectable": True} for i in cdata.columns],
                    data=cdata.to_dict('leads'),
                    editable=True,
                    filter_action="native",
                    sort_action="native",
                    sort_mode="multi",
                    column_selectable="single",
                    row_selectable="multi",
                    row_deletable=False,
                    selected_columns=[],
                    selected_rows=[],
                    page_action="native",
                    page_current= 0,
                    page_size= 10,
                ),
                html.Div(id='datatable-interactivity-container')
            ])
        ])
])

@app.callback(
    Output("graph1", "figure"), 
    Input("rowid_selector", "value"))

def update_value(selected_rowid):
    campaign_summary = df["rowID", "status"]
    campaign_summary_filtered = campaign_summary[campaign_summary.rowID == selected_rowid]
    campaign_summary_filtered["Counts"] = campaign_summary_filtered.groupby(["status"]).transform(len)
    campaign_summary_filtered.set_index("rowID", inplace=True)
    campaign_summary_filtered.drop_duplicates()

    fig = px.histogram(campaign_summary, x=campaign_summary.index, nbins=20, color='status')
    fig.update_layout(bargap=0.2)

    return fig


if __name__ == "__main__":
    app.run_server(debug=False, port=8050)

Any help would be greatly appreciated as I have been going around in circles with the documentation and do not have much hair left on my head!

Hi @nrg and welcome to the forum! :tada:

I understand that the code you copied is just a part of the full app code, right? Because right now only graph1 gets updated and campaign_summary_filtered is not used. I have reviewed your code with some sample data and made some modifications, mainly:

  • campaign_summary = df[["rowID", "status"]] (double brackets instead of single ones)
  • Remove line break after callback
  • Add prevent_initial_call= True to the callback
  • Change debug=True to help solve the potential issues (you can change it back after it stops giving errors but it would help you debug in the meantime)
from dash import dash, dcc, html, dash_table
from dash.dependencies import Input, Output, State
import dash_bootstrap_components as dbc
import plotly.express as px
import plotly.graph_objects as go
import pandas as pd
import numpy as np
import random

#df = pd.read_csv('data2.csv')
#cdata = pd.read_csv('cdata.csv')

df = px.data.tips()
df['rowID'] = [int(random.uniform(1,20)) for i in range(len(df))]
df['status'] = [random.choice(['St1', 'St2']) for i in range(len(df))]
df['solution'] = [random.choice(['Sol1', 'Sol2', 'Sol3']) for i in range(len(df))]
df['Count'] = [1 for i in range(len(df))]
cdata = px.data.tips()

app = dash.Dash(external_stylesheets=[dbc.themes.MINTY])
server = app.server

rowid_options = []
for rowid in df['rowID'].unique():
    rowid_options.append({'label':rowid,'value':rowid})

solution_options = []
for solution in df['solution'].unique():
    solution_options.append({'label':solution,'value':solution})

app.layout = dbc.Container([
    dbc.Row([html.H1("Analytics Dashboard")]),
    dbc.Row([
        html.Label("Select the campaign RowID or Solution that you would like to query from the dropdowns below."),
        dbc.Col([dcc.Dropdown(id = "rowid_selector", options = rowid_options,
        clearable=True, placeholder="Select your RowID")
    ]),
        dbc.Col([dcc.Dropdown(id = "solution_selector", options = solution_options,
        clearable=True, placeholder="Select your Product/Solution")
    ])]),
    dbc.Row([
        dbc.Col([dcc.Graph(
            id='graph1', 
            )
            ]),
        dbc.Col([dcc.Graph(
            id='graph2', figure={}
            )
            ]),
    ]),
    dbc.Row([
        dbc.Col([dcc.Graph(
            id='graph3', figure={}
            )
            ]),
        dbc.Col([dcc.Graph(
            id='graph4', figure={}
            )
            ])
    ]),
        dbc.Row([html.H2("Customer Intent Tracker")]),
        dbc.Row([
            html.Div([
                dash_table.DataTable(
                    id='datatable-interactivity',
                    columns=[{"name": i, "id": i, "deletable": False, "selectable": True} for i in cdata.columns],
                    data=cdata.to_dict('records'),
                    editable=True,
                    filter_action="native",
                    sort_action="native",
                    sort_mode="multi",
                    column_selectable="single",
                    row_selectable="multi",
                    row_deletable=False,
                    selected_columns=[],
                    selected_rows=[],
                    page_action="native",
                    page_current= 0,
                    page_size= 10,
                ),
                html.Div(id='datatable-interactivity-container')
            ])
        ])
])

@app.callback(
    Output("graph1", "figure"), 
    Input("rowid_selector", "value"),
    prevent_initial_call = True)
def update_value(selected_rowid):
    campaign_summary = df[["rowID", "status"]]
    campaign_summary_filtered = campaign_summary[campaign_summary.rowID == selected_rowid]
    campaign_summary_filtered["Counts"] = campaign_summary_filtered.groupby(["status"]).transform(len)
    campaign_summary_filtered.set_index("rowID", inplace=True)
    campaign_summary_filtered.drop_duplicates()


    fig = px.histogram(campaign_summary, x=campaign_summary.index, nbins=20, color='status')
    fig.update_layout(bargap=0.2)

    return fig


if __name__ == "__main__":
    app.run_server(debug=True, port=8050)

The resulting code is this and it works for me. If it doesn’t for you, can you specify which error you are finding? Thanks!