jko0401
February 24, 2021, 6:28pm
1
I’d like to create multiple similar histograms in my Dash layout with a single callback output to a single div instead of repetitively copying and pasting code. Below is an example of my current code:
# In app.layout
html.Div([
html.H3('Plots'),
html.Div(dcc.Graph(id='A')),
html.Div(dcc.Graph(id='B')),
html.Div(dcc.Graph(id='C'))
])
# Callback
@app.callback(
[Output('A', 'figure'),
Output('B', 'figure'),
Output('C', 'figure')]
[Input('filtered-data-hidden', 'children')]
)
def plot_data(df):
dff = pd.read_json(df, orient='split')
figure_a = px.histogram(dff, x="A", nbins=20)
figure_b = px.histogram(dff, x="B", nbins=20)
figure_c = px.histogram(dff, x="C", nbins=20)
return figure_a, figure_b, figure_c
I tried the following:
# In app.layout
html.Div([
html.H3('Plots'),
html.Div(dcc.Graph(id='figures'))
])
# Callback
@app.callback(
Output('figures', 'figure'),
[Input('filtered-data-hidden', 'children')]
)
def plot_data(df):
dff = pd.read_json(df, orient='split')
figures = []
for feature in FEATURES.keys():
figures.append(px.histogram(dff, x=features, nbins=20))
return figures
But got an error:
Invalid argument `figure` passed into Graph with ID "figures".
Expected `object`.
Was supplied type `array`.
Hi @jko0401
The figures id belongs to dcc.graph, which means it’s expecting one figure or an object, not a list of figures that you’re feeding it.
1 Like
jko0401
February 25, 2021, 2:41am
3
I understand that. I was hoping to convey my intention and what I want to achieve. What is the correct syntax for passing a bunch of plotly express graphs to a single div in layout? Is it possible?
xhlu
February 25, 2021, 3:04am
4
Solution #1: Create a bunch of dcc.Graph
and output into a div
# In app.layout
html.Div([
html.H3('Plots'),
html.Div(id='div-figures')
])
# Callback
@app.callback(
Output('div-figures', 'children'),
[Input('filtered-data-hidden', 'children')]
)
def plot_data(df):
dff = pd.read_json(df, orient='split')
figures = []
for feature in FEATURES.keys():
figures.append(dcc.Graph(figure=px.histogram(dff, x=features, nbins=20)))
return figures
Solution #2: Pattern matching callbacks
from dash.dependencies import Input, Output, ALL
# In app.layout
html.Div([
html.H3('Plots'),
html.Div([
dcc.Graph(id={"index": i, "name": "graph"})
for i in range(len(FEATURES))
])
])
# Callback
@app.callback(
Output({"name": "graph", "index": ALL}, 'figure'),
[Input('filtered-data-hidden', 'children')]
)
def plot_data(df):
dff = pd.read_json(df, orient='split')
figures = []
for feature in FEATURES.keys():
figures.append(px.histogram(dff, x=features, nbins=20))
return figures
I haven’t tested the code but it should follow the general pattern for this type of I/Os.
1 Like
jko0401
February 25, 2021, 7:08am
5
solution 1 is straightforward and easy to understand. I never knew about pattern matching callbacks so thank you for introducing and providing it as a solution as well!
1 Like
@xhlu @jko0401
can you please explain to me where FEATURES is coming from. What is that object?
jko0401
February 25, 2021, 11:33pm
7
It is a dictionary that is imported separately that matches the values to labels to display in dropdowns and graphs.