First shot at building a graph in Dash or Plot.ly - Feedback welcome

Hi,

Would love your opinion on the data mapping below. I’m pretty sure I have it all wrong.

  1. I don’t want the figure to be seen until one of the input values from the DataTable is selected. Any parameters or reading you would recommend for me to look into?
  2. Should I pass the full Data Set into the graph first, and then “filter” by mapping the store value into the colour in just one trace, as opposed to looping through the stores and adding traces for each instance?

# Create a Graph that shows the demand for a particular SKU/Generic ID, with different colours for different stores at one site.

fig_product_demand = dcc.Graph(id="demand_graph",
                               figure=None)

chk_product_demand_fill_gaps_checkbox = dbc.Checkbox(id='chk_product_demand_fill_gaps_checkbox',
                                                     label="Connect Lines",
                                                     value=True)

fig_product_demand = dcc.Graph(id="demand_graph",
                               figure=None)

chk_product_demand_fill_gaps_checkbox = dbc.Checkbox(id='chk_product_demand_fill_gaps_checkbox',
                                                     label="Connect Lines",
                                                     value=True)

app.callback(
    Output('demand_graph', 'figure'),
    [Input('dt_product_master', 'active_cell'),
     Input('chk_product_demand_fill_gaps_checkbox', 'value'),
     State('store_multichoice', 'value'),
     State('site_dropdown', 'value')],
    prevent_initial_call=True
)


def update_stock_demand_graph(product_active_cell, connect_lines, stores, site):
    """Updates the Product Demand graph based on the selected active cell within the details of the product that is highlighted at the time.

    Args:
        product_active_cell (Dict): Dictionary of the Active Cell selected in the Product Active Cell.
        stores (List): List of store(s) selected in the drop down.
        site (_type_): Value selected in the Site dropdown.

    Returns:
        figure: Line Graph of demand. Returns False if no transaction/demand data found.
    """
    row = product_active_cell['row_id']
    col = product_active_cell['column_id']
    value = aggregated_store_product_inventory.at[row, col]

    data = df_agg_trans.query(
        f"site_sid=='{site}' and store_xid in {stores} and {col} == {value}")

    if not data:
        return False

    fig = go.Figure()
    for store in stores:
        fig.add_trace(go.Scatter(
            name=store,
            x=data.query(f"store_xid=={store}")['bin_tran_dt'],
            # Invert demand as the system operates as an ioh movement, sold goods are negative because they leave the inventory.
            y=data.query(f"store_xid=={store}")['bin_tran_inven_qty'],
            connectgaps=connect_lines
        ))
    return fig

hi @MrMadium
It would be easier to answer this question if there were a minimal reproducible example present.

What is currently happening?

You could wrap the dcc.Graph() in a html.Div().

Something along the lines of

fig_product_demand = html.Div(id='wrap', children=[])

# and later in your callback return a dcc.Graph() instead of the figure

app.callback(
    Output('wrap', 'children'),
    [Input('dt_product_master', 'active_cell'),
     Input('chk_product_demand_fill_gaps_checkbox', 'value'),
     State('store_multichoice', 'value'),
     State('site_dropdown', 'value')],
    prevent_initial_call=True
)
def update(*args):
    ...
    ...
    return dcc.Graph(id='graph', figure=figure)

Your second point is difficult to answer. I always tend to add a trace for each, series of data, I think you refer to this as “instance”

1 Like