Duplicate callback Output in use

I have a dashboard for displaying historical data alongside forecasted values. I would like the user to be able to make edits to the forecasted values and update the graph. I am accomplishing this through an editable datatable. However I am unsure of how to update the scatter plot after getting user input on the editable datatable.

Example data

item   time_period  number  forecast
apple   1            5         0
apple   2            10        0
apple   3            8         0
apple   4            9         1
apple   5            12        1
orange  1            20        0
orange  2            46        0
orange  3            35        0
orange  4            32        1
orange  5            55        1
import dash_core_components as dcc
import dash_html_components as html
import plotly.express as px
import pandas as pd
import dash_table
from dash.dependencies import Input, Output



external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']

app = dash.Dash(__name__, external_stylesheets=external_stylesheets)

raw_data = {"item": ["apple", "apple", "apple", "apple", "apple", "orange", "orange", "orange", "orange", "orange"], "time_period":[1,2,3,4,5,1,2,3,4,5], "number":[5, 10, 8, 9, 12, 20, 46, 35, 32, 55],
            "forecast": [0,0,0,1,1,0,0,0,1,1]}
df = pd.DataFrame(raw_data)
items = df["item"].unique()

app.layout = html.Div([
    dcc.Graph(
        id="scatter-plot"
    ),
    dcc.Dropdown(
        id="dropdown",
        options=[{"label":i, "value":i} for i in items]
    ),
    dash_table.DataTable(
        id="data-table",
        columns=[{"id": "time_period", "name":"time_period"}, {"id":"number", "name":"number", "editable":True}],
        data=df.to_dict("records")
    )
])

@app.callback(
    Output(component_id="scatter-plot", component_property="figure"),
    Output(component_id="data-table", component_property="data"),
    Input(component_id="dropdown", component_property="value")
)

def select_item(fruit):

    # create copy of original dataframe
    dff = df.copy()

    # isolate out fruit from dropdown
    fruit_df = dff[dff["item"] == fruit]

    # create scatter plot for selected brand
    fig = px.scatter(data_frame=fruit_df, x="time_period", y="number", color="forecast")

    # isolate ordered cases and item
    forecasts = fruit_df[["time_period", "number"]]
    forecasts = forecasts.to_dict("records")

    return fig, forecasts

@app.callback(
    Output(component_id="scatter-plot", component_property="figure"),
    Input(component_id="data-table", component_property="data")
)

def update_scatter(data):
    fig = px.scatter(data_frame=data, x="time_period", y="number")
    return fig

app.run_server(debug=True)

Hi @magladde

You can not assign two different Output to the same id. In your case both callbacks have the same id (id=“scatter-plot”).

Also take in mind that the def function must be right after the @app.callback() without any space.

I made some changes to your code adding an additional graph, now there is another little problem with scatter x definition, you ar passing a string instead of a Series (I think) :thinking:

import dash

import dash_core_components as dcc
import dash_html_components as html
import plotly.express as px
import pandas as pd
import dash_table
from dash.dependencies import Input, Output



external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']

app = dash.Dash(__name__, external_stylesheets=external_stylesheets)

raw_data = {"item": ["apple", "apple", "apple", "apple", "apple", "orange", "orange", "orange", "orange", "orange"], "time_period":[1,2,3,4,5,1,2,3,4,5], "number":[5, 10, 8, 9, 12, 20, 46, 35, 32, 55],
            "forecast": [0,0,0,1,1,0,0,0,1,1]}
df = pd.DataFrame(raw_data)
items = df["item"].unique()

app.layout = html.Div([
    dcc.Dropdown(
        id="dropdown",
        options=[{"label":i, "value":i} for i in items]
    ),
    dcc.Graph(
        id="scatter-plot"
    ),
    dcc.Graph(
        id="scatter-plot2"
    ),
    dash_table.DataTable(
        id="data-table",
        columns=[{"id": "time_period", "name":"time_period"}, {"id":"number", "name":"number", "editable":True}],
        data=df.to_dict("records")
    )
])

@app.callback(
    Output(component_id="scatter-plot", component_property="figure"),
    Output(component_id="data-table", component_property="data"),
    Input(component_id="dropdown", component_property="value")
)
def select_item(fruit):

    # create copy of original dataframe
    dff = df.copy()

    # isolate out fruit from dropdown
    fruit_df = dff[dff["item"] == fruit]

    # create scatter plot for selected brand
    fig = px.scatter(data_frame=fruit_df, x="time_period", y="number", color="forecast")

    # isolate ordered cases and item
    forecasts = fruit_df[["time_period", "number"]]
    forecasts = forecasts.to_dict("records")

    return fig, forecasts

@app.callback(
    Output(component_id="scatter-plot2", component_property="figure"),
    Input(component_id="data-table", component_property="data")
)
def update_scatter(data):
    fig = px.scatter(data_frame=data, x="time_period", y="number")
    return fig


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