✊🏿 Black Lives Matter. Please consider donating to Black Girls Code today.
🧬 Learn how to build RNA-Seq data apps with Python & Dash. Register for the May 20 Webinar!

Is it possible to add traces to a dcc.Graph dinamically?

I will try to explain it clearly.

I am performing a dash application, and I want to dinamically add new traces to a scatter plot. Here is an example of the code.

app = dash.Dash(name, external_stylesheets=[dbc.themes.BOOTSTRAP])
app.scripts.config.serve_locally = True
app.config[‘suppress_callback_exceptions’] = True

app.layout = html.Div([
html.Div([
dcc.Dropdown(id=‘scatterXVar’, value=None, style={‘display’: ‘none’}),
dcc.Dropdown(id=‘scatterYVar’, value=None, style={‘display’: ‘none’}),
], id=‘scatterVariables’),

html.Button(‘Add Trace’, id=‘addTrace’)
)]),

dcc.Graph(id=‘scatterGraph’)

I have two dropdowns in the layout, one corresponds to the X-Variable I want to scatter, and the other one to the Y-Variable.

The idea is, once I have selected which two variables I wanna scatter, whenever I click the button, a trace is added to the graph. My problem is that after I scatter the first trace, whenever I want to add another trace to the graph, the previous traces are erased, and it only adds the new trace, and what I want is to preserve all the traces together.

Here is my callback:

@app.callback(Output(‘scatterGraph’, ‘figure’),
[Input(‘addTrace’, ‘n_clicks’)],
[State(‘scatterXVar’, ‘value’),
State(‘scatterYVar’, ‘value’)])
def sccatterGr(nclicks, scatterXval, scatterYval): # da):
if scatterXval is None or scatterYval is None or scatterXval == or scatterYval == :
return {}
else:
fig = go.Figure()
fig.add_trace(go.Scatter(
x=df[scatterXval.encode(‘utf-8’)],
y=df[scatterYval.encode(‘utf-8’)],
mode=‘markers’,
marker={
‘size’: 15,
‘opacity’: 0.5,
‘line’: {‘width’: 0.5, ‘color’: ‘white’}
}))
return fig

Please, I need help so badly.

I need help please, it’s important. Someone who let me know if it is possible? Thanks

hmm… it seems like what you are trying to do is store the history or traces for a figure so that with each incremental drop down value pair passed in, the graph is updated with the new trace as well as all the previous traces that were generated.

The problem with your current code is that each time the callback is triggered, you are initializing a new empty figure with fig = go.Figure() which is why you are only getting the newly added trace.

I’m not sure how to you can somehow append the traces to a growing list of traces that you can reference each time a callback is generated. I don’t know if this would work but have you tried to not initialize a new empty Figure() in your callback each time.

also try passing in figure as State and then mutating it

Thanks both! I found a solution a few days ago, and it is the one that @chriddyp comments. Passing the figure as State and mutating whenever the callback is generated.

I know it’s a year later but can you link the solution you found? What do you mean by “mutate”?