Overlapping of graphs in subplot plotly

I am trying to make subplots (2x2) but in doing so one plot is overlapping over all others.

Code:

import random
import pandas as pd
import numpy as np
import plotly_express as px
from plotly.subplots import make_subplots
import plotly
import plotly.graph_objects as go
import dash
import dash_core_components as dcc
import dash_html_components as html
import dash_bootstrap_components as dbc
from dash.dependencies import Input, Output, State

df_copy = pd.read_csv("data.csv")

card_graph2 = dbc.Card([dbc.CardBody(dcc.Graph(id="id-graph2", figure={})),])

card_graph1 = dbc.Card(
    [
        dbc.CardBody(
            [
                dcc.Dropdown(
                    id="demo-dropdown",
                    options=[
                        {"label": str(item), "value": str(item)}
                        for item in sorted(df_copy["country_txt"].unique())
                    ],
                    placeholder="Select a country...",
                    value="United States",
                    optionHeight=25,
                    searchable=True,
                    search_value="",
                    clearable=True,
                ),
                dcc.Graph(id="id-graph1", figure={}),
            ],
        ),
    ]
)

card3 = dbc.Card(
    [
        dbc.CardBody(
            [
                dcc.Graph(id="cities", figure={}),
                # dcc.Graph(id="donut", figure={}),
                # dcc.Graph(id="casualities", figure={}),
                # dcc.Graph(id="terror-group", figure={}),
            ]
        )
    ]
)


app = dash.Dash(__name__)

app.layout = html.Div(
    [
        dbc.Row(
            [
                dbc.Col(
                    [
                        dbc.CardHeader(
                            [html.H1("Terrorism Around the Globe"), html.P("")]
                        )
                    ],
                    style={
                        "text-align": "left",
                        "font-size": "100%",
                        "color": "black",
                        "font-weight": "bold",
                        "padding-top": "1px",
                        "padding-right": "1px",
                        "padding-bottom": " 1px",
                        "padding-left": "1px",
                        "margin-left": "2%",
                    },
                ),
                # dbc.Col(
                #     html.Img(
                #         src=app.get_asset_url("terrorism_logo.jpg"),
                #         style={
                #             "height": "60px",
                #             "width": "auto",
                #             "margin": "0px",
                #             "padding-top": "0px",
                #             "padding-bottom": "0px",
                #             "display": "inline",
                #             "float": "right",
                #         },
                #     )
                # ),
            ],
            className="one-third column",
        ),
        dbc.Row(
            [
                dbc.Col(
                    card_graph1,
                    style={
                        "width": "47%",
                        "display": "inline-block",
                        "margin-left": "2%",
                        "padding-top": "0px",
                    },
                ),
                dbc.Col(
                    card_graph2,
                    style={
                        "width": "47%",
                        "display": "inline-block",
                        "margin-right": "2%",
                        "margin-left": "2%",
                    },
                ),
            ],
            justify="around",
        ),
        dbc.Row(dbc.Col(card3, style={"margin-left": "2%", "margin-right": "2%"})),
    ],
    style={"background-color": "#f9f9f9"},
)


@app.callback(Output("id-graph1", "figure"), [Input("demo-dropdown", "value")])
def update_output(value):
    df_sub = df_copy.loc[df_copy["country_txt"] == value]
    random.seed(1)
    # print(df_sub.head())
    # create graph

    location = [
        (
            go.Scattermapbox(
                lon=df_sub["longitude"],
                lat=df_sub["latitude"],
                mode="markers",
                marker=dict(size=10, allowoverlap=False, opacity=0.7, color="crimson"),
                hovertemplate=["casualities:%{casualities_median}", "city:%{city}"],
                hovertext=["casualities_median"],
            )
        )
    ]

    # return graph
    return {
        "data": location,
        "layout": go.Layout(
            uirevision="foo",
            hovermode="closest",
            hoverdistance=2,
            mapbox=dict(
                accesstoken=mapbox_access_token,
                style="light",
                center=dict(
                    lat=random.choice(df_sub["latitude"].tolist()),
                    lon=random.choice(df_sub["longitude"].tolist()),
                ),
                zoom=4,
            ),
        ),
    }


@app.callback(Output("id-graph2", "figure"), [Input("demo-dropdown", "value")])
def update_graph(drop_value):

    dff = df_copy.loc[df_copy["country_txt"] == drop_value]

    fig = px.bar(
        dff["weapon_type"].value_counts()[:10], title=f"Weapons used in {drop_value}"
    )

    return fig


@app.callback(Output("cities", "figure"), [Input("demo-dropdown", "value")])
def subplot_graph(drop_value):
    dff_sub = df_copy.loc[df_copy["country_txt"] == drop_value]

    fig = make_subplots(
        rows=2,
        cols=2,
        specs=[
            [{"type": "bar"}, {"type": "pie"}],
            [{"type": "scatter"}, {"type": "bar"}],
        ],
    )
    # Figure1

    fig.add_trace(
        go.Bar(y=dff_sub["city"].value_counts()[:10]), row=1, col=1,
    )
    # Figure2

    fig.add_trace(
        go.Pie(
            labels=dff_sub["success"].value_counts().index,
            values=dff_sub["success"].value_counts(),
            hole=0.4,
        )
    )

    # Figure3

    fig.add_trace(
        go.Scatter(x=dff_sub["year"], y=dff_sub["casualities"], mode="lines",),
        row=2,
        col=1,
    )
    # Figure4

    fig.add_trace(
        go.Bar(x=dff_sub["group"].value_counts()[:10]), row=2, col=2,
    )

    # fig.layout.yaxis(domain=[0, 0.25], row=1, col=1)
    # fig.layout.yaxis(domain=[0.26, 0.5], row=1, col=2)
    # fig.layout.yaxis(domain=[0.51, 0.75], row=2, col=1)
    # fig.layout.yaxis(domain=[0.76, 1], row=2, col=2)
    fig.update_layout(
        height=800, width=1200, showlegend=False,
    )

    return fig


if __name__ == "__main__":
    app.run_server(debug=False)

Screenshot of Plots:

As you can see pie chart is overlapping and ideally it should be at (row = 1 , col =2) .
In code section , subplot function is the part where changes needs to done for this.

Any help will be highly appreciated.

@matsujju

Redefine subplots as follows:

fig = make_subplots(
        rows=2,
        cols=2,
        specs=[
            [{"type": "bar"}, {"type": "polar"}],
            [{"type": "scatter"}, {"type": "bar"}],
        ]
    )

i.e. replace {"type": "pie"} with {"type": "polar"}.

2 Likes

Thanks for your help.