jko0401
jko0401

Reputation: 47

Plotly Dash callback output array of graphs to a single Div in layout?

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`.

Upvotes: 0

Views: 1213

Answers (1)

bas
bas

Reputation: 15722

You've left out some implementation details in your question so I will give more general examples here to highlight an approach you could take.


An idea is to dynamically create lists of elements based on your keys something like this:

graphs_from_keys = [dcc.Graph(id=key) for key in keys]
outputs_from_keys = [Output(key, "figure") for key in keys]
figures_from_keys = [px.histogram(df, x=key, nbins=20) for key in keys]

This allows us to pass each graph in the graphs_from_keys list to the layout like this:

app.layout = html.Div(
    [
        html.H3("Plots"),
        *graphs_from_keys,
        # ...
    ]
)

and then the callback could look something like this:

@app.callback(
    outputs_from_keys,
    [Input('filtered-data-hidden', 'children')],
)
def plot_data(df):
    # ...
    return figures_from_keys

Upvotes: 2

Related Questions