Dynamic graph and html table have same inputs and structure but table is not functioning or updating properly

I have a Dash app that takes user input on basis values and adjustments and then applies them to a data frame of additional values, sorts and finally publishes a chart and corresponding table of the 10 most economical outcomes. The chart functions perfectly, responding to additional filter options and updates each time user input is changed. My issue is that the table component has the exact same syntax except it returns nothing and no errors are being reported to help me figure out the root.


import datetime
import dash
import dash_core_components as dcc
import dash_html_components as html
import dash_bootstrap_components as dbc
from dash.dependencies import Input, Output
import pandas as pd
import dash_table
import numpy as np
# import plotly.offline as plyo


import cufflinks as cf
app = dash.Dash()

app.layout = html.Div(children=[

    html.Div(children='''
        Associated 10 Basis Price Vector: B1,B2,...,B9,B10
    '''),
    dcc.Input(id='Basis',debounce=True, value='0,0,0,0,0,0,0,0,0,0', type='string'),

    html.Div(children='''
        Adjustments: Premium/Discounts for Basis locations
    '''),
    dcc.Input(id='BasisADJ',debounce=True, value='0,0,0,0,0,0,0,0,0,0', type='string'),

    html.Div(children='''
        Filter_Option:
    '''),
    dcc.Dropdown(
        id='Filter',

        options=[
            {'label': 'Include Only', 'value': 2},
            {'label': 'Exclude', 'value': 1},
            {'label': 'None', 'value': 3}

        ],
        value=3
    ),

    html.Div(children='''
        State:
    '''),
    dcc.Input(id='State', debounce=True,value='TX', type='text'),

    html.Div(id='output-graph'),

    html.Div(
        id = 'output_table1',
        className = 'tableDiv'
    )


])

@app.callback(
    Output(component_id='output-graph', component_property='children'),
    [Input(component_id='Basis', component_property='value'),Input(component_id='BasisADJ', component_property='value'),Input(component_id='State', component_property='value'),Input(component_id='Filter', component_property='value')]
)


def update_value(Basis_data,BasisADJ_data,State_data,Filter_data):




    Basis = [sum(x) for x in zip([int(x) for x in Basis_data.split(',')], [int(x) for x in BasisADJ_data.split(',')])]

    df = pd.read_pickle('//home//HartWheat//mysite//Rail_Rates')
    # df = pd.read_pickle('C:\\Users\\dwyczolkowski\\FREIGHTVALUES_test')


    dfM=pd.DataFrame(columns=['BROWNSVILLE', 'EAGLEPASS', 'LAREDO', 'ELPASO', 'NOGALES',
       'CALEXICO'], index=['M1','M2','M3','M4','M5','M6'])
    dfM['BROWNSVILLE']=[4582,6528,9245,3852,4925,5100]
    dfM['EAGLEPASS']=[4900,5900,6200,3900,5200,6300]
    dfM['LAREDO']=[6200,4100,5400,6200,3600,4200]
    dfM['ELPASO']=[4200,4300,5400,4200,6822,5422]
    dfM['NOGALES']=[5200,5100,3300,4800,5100,5300]
    dfM['CALEXICO']=[6400,5800,4200,3200,4600,5100]

    # dfMdict=dfM.to_dict()


    dfM_Long=dfM.stack().reset_index()
    dfM_Long.columns=('MEX_DEST','DEST','MEX_RATES')
    masterRail=pd.merge(df, dfM_Long, how='right', on='DEST')
    masterRail['Total_Rail_Cost']=masterRail['RAIL_COST']+masterRail['MEX_RATES']

    if Filter_data == 1:
        masterRail=masterRail[~masterRail.ORIGIN.str.contains(State_data+',')]

    elif Filter_data == 2:
        masterRail=masterRail[masterRail.ORIGIN.str.contains(State_data+',')]

    elif Filter_data == 3:
        masterRail=masterRail.sort_values(['Total_Rail_Cost'])
    masterRail=masterRail.sort_values(['Total_Rail_Cost'])
    mRail10=masterRail[:10].copy()
    mRail10['Basis']=Basis
    mRail10['Total_Rail_and_Basis']=mRail10['Basis']+mRail10['Total_Rail_Cost']

    mRail10=mRail10.sort_values(['Total_Rail_and_Basis'])
    mRail10['Route']=mRail10['ORIGIN']+'_VIA_'+mRail10['DEST']+'_TO_'+mRail10['MEX_DEST']

    return dcc.Graph(
            id='example-graph',
            figure=mRail10.iplot(asFigure=True ,kind='bar',y= 'Total_Rail_and_Basis' ,bargap=.5, theme ='solar',x='Route',xTitle='Route Ordered By Cheapest To Deliver',yTitle='Total Cost',title='Optimized Wheat Delivery')
        )


#@app.callback(
#    Output('output_table1', 'children'),
#    [Input(component_id='Basis', component_property='value'),Input(component_id='BasisADJ', component_property='value'),Input(component_id='State', component_property='value'),Input(component_id='Filter', component_property='value')]
#)
@app.callback(
    Output(component_id='output-table1', component_property='children'),
    [Input(component_id='Basis', component_property='value'),Input(component_id='BasisADJ', component_property='value'),Input(component_id='State', component_property='value'),Input(component_id='Filter', component_property='value')]
)
def update_table(Basis_data,State_data,Filter_data,BasisADJ_data):


        Basis = [sum(x) for x in zip([int(x) for x in Basis_data.split(',')], [int(x) for x in BasisADJ_data.split(',')])]

        df = pd.read_pickle('//home//HartWheat//mysite//Rail_Rates')
        # df = pd.read_pickle('C:\\Users\\dwyczolkowski\\FREIGHTVALUES_test')


        dfM=pd.DataFrame(columns=['BROWNSVILLE', 'EAGLEPASS', 'LAREDO', 'ELPASO', 'NOGALES',
           'CALEXICO'], index=['M1','M2','M3','M4','M5','M6'])
        dfM['BROWNSVILLE']=[4582,6528,9245,3852,4925,5100]
        dfM['EAGLEPASS']=[4900,5900,6200,3900,5200,6300]
        dfM['LAREDO']=[6200,4100,5400,6200,3600,4200]
        dfM['ELPASO']=[4200,4300,5400,4200,6822,5422]
        dfM['NOGALES']=[5200,5100,3300,4800,5100,5300]
        dfM['CALEXICO']=[6400,5800,4200,3200,4600,5100]

        # dfMdict=dfM.to_dict()


        dfM_Long=dfM.stack().reset_index()
        dfM_Long.columns=('MEX_DEST','DEST','MEX_RATES')
        masterRail=pd.merge(df, dfM_Long, how='right', on='DEST')
        masterRail['Total_Rail_Cost']=masterRail['RAIL_COST']+masterRail['MEX_RATES']

        if Filter_data == 1:
            masterRail=masterRail[~masterRail.ORIGIN.str.contains(State_data+',')]

        elif Filter_data == 2:
            masterRail=masterRail[masterRail.ORIGIN.str.contains(State_data+',')]

        elif Filter_data == 3:
            masterRail=masterRail.sort_values(['Total_Rail_Cost'])
        masterRail=masterRail.sort_values(['Total_Rail_Cost'])

        mRail10=masterRail[:10].copy()
        mRail10['Basis']=Basis
        mRail10['Total_Rail_and_Basis']=mRail10['Basis']+mRail10['Total_Rail_Cost']

        mRail10=mRail10.sort_values(['Total_Rail_and_Basis'])
        mRail10['Route']=mRail10['ORIGIN']+'_VIA_'+mRail10['DEST']+'_TO_'+mRail10['MEX_DEST']


        return html.Div([html.Label('Optimized Wheat Delivery'),
                dash_table.DataTable(
            id='table',
            columns=[{"name": i, "id": i} for i in mRail10.columns],
            data=mRail10.to_dict('records'))
        ])


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

Hi,

Your problem is that you defined the div with id="output_table1" (with underscore) and the callback uses component_id='output-table1' (with dash).

Besides, you should seriously consider having a single callback updating both the graph and the table, just add them as a list of outputs in the callback signature and return a list with the two components as you are returning now.

1 Like

Brilliant, the single call back list output is exactly what I was looking for. Thank you so much for your quick reply and assistance.