✊🏿 Black Lives Matter. Please consider donating to Black Girls Code today.
🐇 Announcing Dash VTK for 3d simulation graphics. Check out the March webinar.

Graph Not Updating Properly

Hey Everyone,

I am currently in the process of creating a simple dashboard which tracks the volume and type calls by user(s) within our team utilizing a multi input and output callback.

Upon page load the dataset is read from a mysql database and loaded into Dash’s DataTable.
This db is then additionally filtered through two input types, a date picker range and a multi-value dropdown (with two values loaded by default).

What’s interesting is that whenever I enter inputs that do not exist in the dataset, the outputs, in this case additional charts and tables still reflect the previous output data instead of changing to blank.
However, if I enter different inputs that do exist in the dataset, then the outputs get updated.

As an example, let’s say I want to look up the number of calls for user X for the date range May 16th through to the 20th. The output will show the volume of calls, duration etc.
However, if I change the date range for dates where I know X was not active, the outputs will keep the previous loaded data instead of going blank.
Once I do change the inputs to values that exist for X, then the outputs will update again.

Hopefully this makes sense.

I believe I have tried everything possible but can’t seem to fix this.

Here is the portion of the code which includes the callback:

@app.callback(
    [Output('chart-source', 'figure'),
     Output('chart-avg-calls', 'figure'),
     Output('table-summary','data'),
     Output('table-summary','columns')],
    [Input('table', 'data'),
     Input('date-picker-range', 'start_date'),
     Input('date-picker-range', 'end_date'),
     Input('user', 'value')])

def update_data(data, start_date, end_date, value):
    updated_data = pd.DataFrame.from_dict(data)

    filtered_data = pd.DataFrame()

    for i in value:
        filtered_data = filtered_data.append(updated_data[(updated_data['Time Start'] >= start_date) & (updated_data['Time Start'] < end_date) & (updated_data['User'] == i)])

    fig_source = {
        'data': [dict(
            type='histogram',
            x=filtered_data[filtered_data['Source'] != ""]['Source'],
            marker={'color':'#03a9f4'},
            hoverinfo="x+y",
            hoverlabel={
                'bgcolor':'#ec407a'
            }
        )],
        'layout': dict(
            yaxis={
                'title': 'Number of Calls'
            },
            xaxis={
                'tickangle': -90,
                'categoryorder': 'total descending'
                },
            margin={'l': 40, 'b': 150, 't': 80, 'r': 0},
            hovermode='closest',
            title='Calls by Source'
        )
    }

    user_summary = filtered_data.copy()
    avg_calls = filtered_data.copy()
    averages = avg_calls.groupby(['Day','Hour'])['Call Type'].count().reset_index()

    data_summary = {
        'Total No. of Calls':[user_summary['User'].count()],
        'Onnet Calls':[user_summary[user_summary['Call Type'] == 'onnet']['User'].count()],
        'Avg. No./Hour':[round(user_summary.groupby(['Day','Hour'])['Call Type'].count().reset_index().groupby(['Hour'])['Call Type'].mean().reset_index()['Call Type'].mean(),2)],
        'Avg. Duration':[str(datetime.timedelta(seconds = round(user_summary['Duration'].mean(),0)))]
    }

    df_summary = pd.DataFrame(data_summary, columns = ['Total No. of Calls','Onnet Calls','Avg. No./Hour','Avg. Duration'])

    columns_summary = [{"name": i, "id": i} for i in df_summary]

    fig_avg_calls = {
        'data': [dict(
            type='bar',
            x=sorted(averages['Hour'].unique()),
            y=averages.groupby(['Hour'])['Call Type'].mean().reset_index()['Call Type'],
            marker={'color':'#03a9f4'},
            hoverinfo="y",
            hoverlabel={
                'bgcolor':'#ec407a'
            }
        )],
        'layout': dict(
            yaxis={
                'title': 'Number of Calls'
            },
            xaxis={
               'tickmode': 'array',
               'tickvals': list(range(0,24)),
               'nticks': 24,
               'tick0': 0,
               'dtick': 1,
               'title':'Hour'
            },
            hovermode='closest',
            title='Avg. Number of Calls by Time of Day'
        )
    }



    return [fig_source, fig_avg_calls, df_summary.to_dict('records'), columns_summary]

Thank you in advance for your help!

Cheers

Hi @francismueller welcome to the forum! It’s not easy to debug without a reproducible example, did you try to print fig_source and fig_avg_calls inside the callback to see whether they correspond to what you are expecting? Also if a Python error is raised inside the callback then the component will not update, maybe this is what happens. Are you using debug=True when running the app?

Hi @Emmanuelle,

Thank you very much for your response!

I am using debug=True, which I had completely forgotten.

While going through the error log, I believe I was able to identify what was causing the issue and as a result had modified one section of the code to this:

    try:
        data_summary = {
            'Total No. of Calls':[user_summary['User'].count()],
            'Onnet Calls':[user_summary[user_summary['Call Type'] == 'onnet']['User'].count()],
            'Avg. No./Hour':[round(user_summary.groupby(['Day','Hour'])['Call Type'].count().reset_index().groupby(['Hour'])['Call Type'].mean().reset_index()['Call Type'].mean(),2)],
            'Avg. Duration':[str(datetime.timedelta(seconds = round(user_summary['Duration'].mean(),0)))]
        }
    except:
        data_summary = {
            'Total No. of Calls':[0],
            'Onnet Calls':[0],
            'Avg. No./Hour':[0],
            'Avg. Duration':[0]
        }

Which seems to work now but I will need to test this out further.

I guess the lack of enough sleep due to work led to me blanking on this, sorry.

Thank you again for your help! :slight_smile:

Cheers