Black Lives Matter. Please consider donating to Black Girls Code today.

Two graphs side by side then next row, etc

Hi,

I see this post on how to create two graphs side by side: Two graphs, side by side

Now, what happens if my app returns a list of graphs (unknown number of graphs), and I want to put them side by side two at a time, i.e.,

graph1 | graph2
graph3 | graph4
etc.

How can I do that in a general way?

The current code I have does not put them side by side, rather one graph per row:

app = dash.Dash()

app.layout = html.Div(children=[
    html.H1(children='Daily Charts by Region'),

    dcc.Dropdown(id='regions',
                 options=[
                     {'label': 'RM', 'value': 'RM'},
                     {'label': 'Valparaiso', 'value': 'Valparaiso'},
                     {'label': 'concepcion', 'value': 'Concepcion'}
                 ],
                 value=['RM','Valparaiso','Concepcion'],
                 multi=True
                 ),

    html.Div(id='graphs')

])


@app.callback(
    Output('graphs', 'children'),
    [Input('regions', 'value')])
def update_graph(regions):
    my_df = getMyDf()
    graphs=[]
    for region in regions:
        fig = myPlot(my_df, region)
        graphs.append(
            dcc.Graph(
                id=region,
                figure=fig
            )
        )
    return graphs

Hello, I encountered a similar problem before, here was how I roughly achieve this:

  • Create a parent div to hold all the graphs (like all the lines of graphs).
  • Write a for loop that starts with i = 0, i += 1 each iteration, for each iteration do:
    ** if i % 2 == 0, then append an empty row to the Div, append a column width 6 containing the next graph into that new row, then next.
    ** if i % 2 == 1, then only append the next graph within a column width 6 into the latest row.
    ** if i == number of graphs, break the loop.
  • Return the gigantic div to render in the app.
1 Like

Hi, thanks for the response.

So, to be more specific, right now my app.callback function returns a list of dcc.Graph objects. Should I still return this?

How should the parent div look like? html.Div(id=‘graphs’, children=[here is where i write the for loop?])

An alternative would be to use Plotly’s subplots feature (https://plot.ly/python/subplots/). Dash would then see this as one ‘figure’ object. You would, of course, have to adapt your myPlot function and callback to reflect those changes.

3 Likes

Hi @dnaiel , my solution was to have the callback function return a Div in which children are rows, each row contains 2 graphs.
So technically, if my list have 9 graphs, then my solution would be to return a Div with 5 rows in it, each row has 2 graphs in 2 columns of width 6, except for the last one which has only 1 graph.
@mikesmith1611 suggested using subplots by Plotly, which I think would be much easier than my solution. Admittedly when I started out with Dash I didn’t know fully all the features of plotly so glad to see that they have subplots. In that case, the list of graphs would be one graph with n subplots.

2 Likes

one reason you may prefer multiple plots to a subplot is the ease with which you can save individual graphs
i have found trying to save 5 rows of graphs to an offline png you lose all the height dimensions set in plotly