dash 在选项卡中动态生成图形

dash dynamically generating graphs in tabs

我有一个印度各州的下拉列表。
选择一个州后,应在不同的选项卡下生成不同的图表。
我总共要生成 6 个图表和 3 个选项卡即,'convicts'、'under_trial'、'detenues'。
每个选项卡将包含 2 个图表。

这些图表是

  • 罪犯的性别和种姓分布
  • under_trial 的性别和种姓分布 under_trial
  • 被拘留者的性别和种姓分布
    基于下拉值选定的印度邦。

    我想创建这样的东西。

    这里是使用的dataset

    导入的库

    import pandas as pd
    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
    import plotly.express as px
    

    Dash 网络应用程序初始化

    app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
    

    Pandas 数据帧加载

    df = pd.read_csv("Caste.csv")
    

    定义的下拉菜单和图形函数

    def dropdown():
        return html.Div([dcc.Dropdown(id='dropdown',
                                      options=[{'label': i, 'value': i} for i in df["state_name"].unique()],
                                      value="Gujarat")]
                        ,className="dropdown")
    
    def graph1_convicts():
        return dcc.Graph(id="graph1_convicts")
    
    def graph2_convicts():
        return dcc.Graph(id="graph2_convicts")
    
    def graph1_under_trial():
        return dcc.Graph(id="graph1_under_trial")
    
    def graph2_under_trial():
        return dcc.Graph(id="graph2_under_trial")
    
    def graph1_detenues():
        return dcc.Graph(id="graph1_detenues")
    
    def graph2_detenues():
        return dcc.Graph(id="graph2_detenues")
    

    布局

    app.layout = dbc.Container([
                                dbc.Row([dbc.Col([html.Div("Indian Prison Stats between 2001-2013", className="heading")])]),
                                dbc.Row([dbc.Col(dropdown())]),
                                dcc.Tabs(id="tabs-selector",
                                         value="tab-1",
                                         className="custom-tabs-container",
                                         children=[
                                                    dcc.Tab(label="Convicts",
                                                            value="tab-1",
                                                            className="custom-tab",
                                                            children=[html.Div([graph1_convicts(),
                                                                                html.Br(),
                                                                                graph2_convicts()]),
                                                                      ]),
                                                    dcc.Tab(label="under_trial",
                                                            value="tab-2",
                                                            className="custom-tab",
                                                            children=[html.Div([graph1_under_trial(),
                                                                                html.Br(),
                                                                                graph2_under_trial()]),
                                                                      ]),
                                                    dcc.Tab(label="detenues",
                                                            value="tab-3",
                                                            className="custom-tab",
                                                            children=[html.Div([graph1_detenues(),
                                                                                html.Br(),
                                                                                graph2_detenues()]),
                                                                      ]),
                                         ]),
    ])
    

    回调

    @app.callback([Output('graph1_convicts', 'figure'),
                   Output('graph2_convicts', 'figure'),
                   Output("graph1_under_trial", "figure"),
                   Output("graph2_under_trial", "figure"),
                   Output("graph1_detenues", "figure"),
                   Output("graph2_detenues", "figure")],
                  [Input('dropdown', 'value'),
                   Input("tabs-selector", "value")])
    
    def update_graph(dropdown, tab):
        # df1_convicts has only convicts column kept, rest all removed, and groupby is done on gender column
        df1_convicts = df[df["state_name"]==dropdown]
        df1_convicts = df1_convicts.drop(["is_state", "caste", "under_trial", "detenues", "others"], axis=1)
        df1_convicts = df1_convicts.groupby(['state_name', "year", "gender"])['convicts'].sum().reset_index()
    
        # df2_convicts has only convicts column kept, rest all removed, and groupby is done on caste column
        df2_convicts = df[df["state_name"]==dropdown]
        df2_convicts = df2_convicts.drop(["is_state", "gender", "under_trial", "detenues", "others"], axis=1)
        df2_convicts = df2_convicts.groupby(["state_name", "year", "caste"])["convicts"].sum().reset_index()
    
        # df1_under_trial has only under_trial column kept, rest all removed, and groupby is done on gender column
        df1_under_trial = df[df["state_name"]==dropdown]
        df1_under_trial = df1_under_trial.drop(["is_state", "caste", "convicts", "detenues", "others"], axis=1)
        df1_under_trial = df1_under_trial.groupby(['state_name', "year", "gender"])['under_trial'].sum().reset_index()
    
        # df2_under_trial has only under_trial column kept, rest all removed, and groupby is done on caste column
        df2_under_trial = df[df["state_name"]==dropdown]
        df2_under_trial = df2_under_trial.drop(["is_state", "gender", "convicts", "detenues", "others"], axis=1)
        df2_under_trial = df2_under_trial.groupby(["state_name", "year", "caste"])["under_trial"].sum().reset_index()
    
        # df1_detenues has only detenues column kept, rest all removed, and groupby is done on gender column
        df1_detenues = df[df["state_name"]==dropdown]
        df1_detenues = df1_detenues.drop(["is_state", "caste", "convicts", "under_trial", "others"], axis=1)
        df1_detenues = df1_detenues.groupby(['state_name', "year", "gender"])['detenues'].sum().reset_index()
    
        # df2_under_trial has only under_trial column kept, rest all removed, and groupby is done on caste column
        df2_detenues = df[df["state_name"]==dropdown]
        df2_detenues = df2_detenues.drop(["is_state", "gender", "convicts", "under_trial", "others"], axis=1)
        df2_detenues = df2_detenues.groupby(["state_name", "year", "caste"])["detenues"].sum().reset_index()
    
    
        fig1_convicts = px.bar(df1_convicts, x="year", y="convicts", color="gender", title="gender distribution of convicts",
                                color_discrete_sequence=px.colors.qualitative.Set1, opacity=0.6)
        fig2_convicts = px.bar(df2_convicts, x="year", y="convicts", color="caste", title="caste distribution of convicts",
                                color_discrete_sequence=px.colors.qualitative.Set1, opacity=0.6)
    
        fig1_under_trial = px.bar(df1_under_trial, x="year", y="under_trial", color="gender", title="gender distribution of under_trial",
                                    color_discrete_sequence=px.colors.qualitative.Set1, opacity=0.6)
        fig2_under_trial = px.bar(df2_under_trial, x="year", y="under_trial", color="caste", title="caste distribution of under_trial",
                                    color_discrete_sequence=px.colors.qualitative.Set1, opacity=0.6)
    
        fig1_detenues = px.bar(df1_detenues, x="year", y="detenues", color="gender", title="gender distribution of detenues",
                                color_discrete_sequence=px.colors.qualitative.Set1, opacity=0.6)
        fig2_detenues = px.bar(df2_detenues, x="year", y="detenues", color="caste", title="caste distribution of detenues",
                                color_discrete_sequence=px.colors.qualitative.Set1, opacity=0.6)
    
        if tab=="tab-1":
            return fig1_convicts, fig2_convicts
        elif tab=="tab-3":
            return fig1_detenues, fig2_detenues
        elif tab=="tab-2":
            return fig1_under_trial, fig2_under_trial
    
    
    if __name__ == '__main__':
        app.run_server(debug=True, port=5050)
    

    如何定义回调?
    我可以轻松地创建罪犯或 under_trial 或 detenues 的性别和种姓分布。但是,我对如何根据下拉值在 3 个选项卡下显示所有 6 个图表感到困惑。
    我在网上搜索了一下,发现dcc.State在这种情况下可能会有用,但我无法正确理解它。

  • 第一件事是您需要 return 您在回调中定义的所有输出。

    在你的情况下,你需要 6 个输出到这个回调

    现在我认为您有 2 个选择:

    1. 当您更改下拉菜单时生成所有图表,它将与当前联系人布局一起使用

    2. 切换标签时仅保持 1 个标签联系人并仅动态创建 2 个图表

    选项 1 代码应如下所示:

    @app.callback([Output('graph1_convicts', 'figure'),
                   Output('graph2_convicts', 'figure'),
                   Output("graph1_under_trial", "figure"),
                   Output("graph2_under_trial", "figure"),
                   Output("graph1_detenues", "figure"),
                   Output("graph2_detenues", "figure")],
                  [Input('dropdown', 'value')])
    
    def update_graph(dropdown):
        # df1_convicts has only convicts column kept, rest all removed, and groupby is done on gender column
        df1_convicts = df[df["state_name"]==dropdown]
        df1_convicts = df1_convicts.drop(["is_state", "caste", "under_trial", "detenues", "others"], axis=1)
        df1_convicts = df1_convicts.groupby(['state_name', "year", "gender"])['convicts'].sum().reset_index()
    
        # df2_convicts has only convicts column kept, rest all removed, and groupby is done on caste column
        df2_convicts = df[df["state_name"]==dropdown]
        df2_convicts = df2_convicts.drop(["is_state", "gender", "under_trial", "detenues", "others"], axis=1)
        df2_convicts = df2_convicts.groupby(["state_name", "year", "caste"])["convicts"].sum().reset_index()
    
        # df1_under_trial has only under_trial column kept, rest all removed, and groupby is done on gender column
        df1_under_trial = df[df["state_name"]==dropdown]
        df1_under_trial = df1_under_trial.drop(["is_state", "caste", "convicts", "detenues", "others"], axis=1)
        df1_under_trial = df1_under_trial.groupby(['state_name', "year", "gender"])['under_trial'].sum().reset_index()
    
        # df2_under_trial has only under_trial column kept, rest all removed, and groupby is done on caste column
        df2_under_trial = df[df["state_name"]==dropdown]
        df2_under_trial = df2_under_trial.drop(["is_state", "gender", "convicts", "detenues", "others"], axis=1)
        df2_under_trial = df2_under_trial.groupby(["state_name", "year", "caste"])["under_trial"].sum().reset_index()
    
        # df1_detenues has only detenues column kept, rest all removed, and groupby is done on gender column
        df1_detenues = df[df["state_name"]==dropdown]
        df1_detenues = df1_detenues.drop(["is_state", "caste", "convicts", "under_trial", "others"], axis=1)
        df1_detenues = df1_detenues.groupby(['state_name', "year", "gender"])['detenues'].sum().reset_index()
    
        # df2_under_trial has only under_trial column kept, rest all removed, and groupby is done on caste column
        df2_detenues = df[df["state_name"]==dropdown]
        df2_detenues = df2_detenues.drop(["is_state", "gender", "convicts", "under_trial", "others"], axis=1)
        df2_detenues = df2_detenues.groupby(["state_name", "year", "caste"])["detenues"].sum().reset_index()
    
    
        fig1_convicts = px.bar(df1_convicts, x="year", y="convicts", color="gender", title="gender distribution of convicts",
                                color_discrete_sequence=px.colors.qualitative.Set1, opacity=0.6)
        fig2_convicts = px.bar(df2_convicts, x="year", y="convicts", color="caste", title="caste distribution of convicts",
                                color_discrete_sequence=px.colors.qualitative.Set1, opacity=0.6)
    
        fig1_under_trial = px.bar(df1_under_trial, x="year", y="under_trial", color="gender", title="gender distribution of under_trial",
                                    color_discrete_sequence=px.colors.qualitative.Set1, opacity=0.6)
        fig2_under_trial = px.bar(df2_under_trial, x="year", y="under_trial", color="caste", title="caste distribution of under_trial",
                                    color_discrete_sequence=px.colors.qualitative.Set1, opacity=0.6)
    
        fig1_detenues = px.bar(df1_detenues, x="year", y="detenues", color="gender", title="gender distribution of detenues",
                                color_discrete_sequence=px.colors.qualitative.Set1, opacity=0.6)
        fig2_detenues = px.bar(df2_detenues, x="year", y="detenues", color="caste", title="caste distribution of detenues",
                                color_discrete_sequence=px.colors.qualitative.Set1, opacity=0.6)
    
            return fig1_convicts, fig2_convicts,
                   fig1_under_trial, fig2_under_trial,
                   fig1_detenues, fig2_detenues
    

    对于选项 2,您可以看到 https://dash.plotly.com/dash-core-components/tabs 它是示例中的第一个选项