pythonhtmlplotlyplotly-dash

How to add multiple graphs to Dash app on a single browser page?


enter image description here

How do I add multiple graphs show in in picture on a same page? I am trying to add html.Div components to following code to update the page layout to add more graphs like that on single page, but these newly added graphs do not get shown on a page, only old graph is shown in picture is visible. What element should I modify, to let's say to add graph shown in uploaded image 3 times on single page of dash app on browser?


import dash
import dash_core_components as dcc
import dash_html_components as html
i[enter image description here][1]mport plotly.express as px
import pandas as pd

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

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

# assume you have a "long-form" data frame
# see https://plotly.com/python/px-arguments/ for more options
df = pd.DataFrame({
    "Fruit": ["Apples", "Oranges", "Bananas", "Apples", "Oranges", "Bananas"],
    "Amount": [4, 1, 2, 2, 4, 5],
    "City": ["SF", "SF", "SF", "Montreal", "Montreal", "Montreal"]
})

fig = px.bar(df, x="Fruit", y="Amount", color="City", barmode="group")

app.layout = html.Div(children=[
    html.H1(children='Hello Dash'),

    html.Div(children='''
        Dash: A web application framework for Python.
    '''),

    dcc.Graph(
        id='example-graph',
        figure=fig
    )
])

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

Solution

  • To add the same figure multiple times, you just need to extend your app.layout. I have extended you code below as an example.

    import dash
    import dash_core_components as dcc
    import dash_html_components as html
    from dash.dependencies import Input, Output
    import pandas as pd
    import plotly.express as px
    
    external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
    
    app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
    
    # assume you have a "long-form" data frame
    # see https://plotly.com/python/px-arguments/ for more options
    df_bar = pd.DataFrame({
        "Fruit": ["Apples", "Oranges", "Bananas", "Apples", "Oranges", "Bananas"],
        "Amount": [4, 1, 2, 2, 4, 5],
        "City": ["SF", "SF", "SF", "Montreal", "Montreal", "Montreal"]
    })
    
    fig = px.bar(df_bar, x="Fruit", y="Amount", color="City", barmode="group")
    
    app.layout = html.Div(children=[
        # All elements from the top of the page
        html.Div([
            html.H1(children='Hello Dash'),
    
            html.Div(children='''
                Dash: A web application framework for Python.
            '''),
    
            dcc.Graph(
                id='graph1',
                figure=fig
            ),  
        ]),
        # New Div for all elements in the new 'row' of the page
        html.Div([
            html.H1(children='Hello Dash'),
    
            html.Div(children='''
                Dash: A web application framework for Python.
            '''),
    
            dcc.Graph(
                id='graph2',
                figure=fig
            ),  
        ]),
    ])
    
    if __name__ == '__main__':
        app.run_server(debug=True)
    

    enter image description here

    The way I have structured the layout is by nesting the html.Div components. For every figure and corresponding titles, text, etc. we make another html.Div that makes a new 'row' in our application.

    The one thing to keep in mind is that different components need unique ids. In this example we have the same graph displayed twice, but they are not the exact same object. We are making two dcc.Graph objects using the same plotly.express figure

    I have made another example for you where I have a added another figure that is dynamic. The second figure is updated every time a new colorscale is selected from the dropdown menu. This is were the real potential of Dash lies. You can read more about callback functions in this tutorial

    import dash
    import dash_core_components as dcc
    import dash_html_components as html
    from dash.dependencies import Input, Output
    import pandas as pd
    import plotly.express as px
    
    external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
    
    app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
    
    # assume you have a "long-form" data frame
    # see https://plotly.com/python/px-arguments/ for more options
    df_bar = pd.DataFrame({
        "Fruit": ["Apples", "Oranges", "Bananas", "Apples", "Oranges", "Bananas"],
        "Amount": [4, 1, 2, 2, 4, 5],
        "City": ["SF", "SF", "SF", "Montreal", "Montreal", "Montreal"]
    })
    
    fig = px.bar(df_bar, x="Fruit", y="Amount", color="City", barmode="group")
    
    # Data for the tip-graph
    df_tip = px.data.tips()
    
    app.layout = html.Div(children=[
        # All elements from the top of the page
        html.Div([
            html.H1(children='Hello Dash'),
    
            html.Div(children='''
                Dash: A web application framework for Python.
            '''),
    
            dcc.Graph(
                id='example-graph',
                figure=fig
            ),  
        ]),
        # New Div for all elements in the new 'row' of the page
        html.Div([ 
            dcc.Graph(id='tip-graph'),
            html.Label([
                "colorscale",
                dcc.Dropdown(
                    id='colorscale-dropdown', clearable=False,
                    value='bluyl', options=[
                        {'label': c, 'value': c}
                        for c in px.colors.named_colorscales()
                    ])
            ]),
        ])
    ])
    
    # Callback function that automatically updates the tip-graph based on chosen colorscale
    @app.callback(
        Output('tip-graph', 'figure'),
        [Input("colorscale-dropdown", "value")]
    )
    def update_tip_figure(colorscale):
        return px.scatter(
            df_tip, x="total_bill", y="tip", color="size",
            color_continuous_scale=colorscale,
            render_mode="webgl", title="Tips"
        )
    
    if __name__ == '__main__':
        app.run_server(debug=True)
    

    enter image description here

    Your next question may be, how do i place multiple figures side by side? This is where CSS and stylesheets are important.

    You have already added an external stylesheet https://codepen.io/chriddyp/pen/bWLwgP.css, which enables us to better structure our layout using the className component of divs.

    The width of a web page is set to 12 columns no matter the screen size. So if we want to have two figures side by side, each occupying 50% of the screen they need to fill 6 columns each.

    We can achieve this by nesting another html.Div as our top half row. In this upper div we can have another two divs in which we specify the style according to classname six columns. This splits the first row in two halves

    import dash
    import dash_core_components as dcc
    import dash_html_components as html
    from dash.dependencies import Input, Output
    import pandas as pd
    import plotly.express as px
    from jupyter_dash import JupyterDash
    
    external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
    
    app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
    
    # assume you have a "long-form" data frame
    # see https://plotly.com/python/px-arguments/ for more options
    df_bar = pd.DataFrame({
        "Fruit": ["Apples", "Oranges", "Bananas", "Apples", "Oranges", "Bananas"],
        "Amount": [4, 1, 2, 2, 4, 5],
        "City": ["SF", "SF", "SF", "Montreal", "Montreal", "Montreal"]
    })
    
    fig = px.bar(df_bar, x="Fruit", y="Amount", color="City", barmode="group")
    
    app.layout = html.Div(children=[
        # All elements from the top of the page
        html.Div([
            html.Div([
                html.H1(children='Hello Dash'),
    
                html.Div(children='''
                    Dash: A web application framework for Python.
                '''),
    
                dcc.Graph(
                    id='graph1',
                    figure=fig
                ),  
            ], className='six columns'),
            html.Div([
                html.H1(children='Hello Dash'),
    
                html.Div(children='''
                    Dash: A web application framework for Python.
                '''),
    
                dcc.Graph(
                    id='graph2',
                    figure=fig
                ),  
            ], className='six columns'),
        ], className='row'),
        # New Div for all elements in the new 'row' of the page
        html.Div([
            html.H1(children='Hello Dash'),
    
            html.Div(children='''
                Dash: A web application framework for Python.
            '''),
    
            dcc.Graph(
                id='graph3',
                figure=fig
            ),  
        ], className='row'),
    ])
    
    if __name__ == '__main__':
        app.run_server(debug=True)
    

    enter image description here