【问题标题】:Is it possible to use zoom from one graph in a Dash app to select input for second graph是否可以使用 Dash 应用程序中一个图形的缩放来选择第二个图形的输入
【发布时间】:2023-01-16 17:41:10
【问题描述】:

我有一个破折号应用程序,它绘制一个数据框,该数据框有一个日期组件,以及一个为真或假的条目。仪表板中有两张图,一张是数据与日期的关系,另一张是真/假百分比,如下所示:

我可以放大日期范围并用鼠标单击选择一个子集。

我想将这个范围反馈到第二张图中。

目前要生成上述仪表板,代码的相关部分如下所示:

from re import template

import pandas as pd
import plotly.express as px
from dash import Dash, Input, Output, dcc, html
from flask import globals


def init_dashboard(server):


    evicted_df = pd.read_csv("app/data/evicted_jobs_node.csv", sep="\t")
    all_df = pd.read_csv("app/data/all_jobs_node.csv", sep="\t")
    all_df["datetime"] = pd.to_datetime(all_df["datetime"])
    all_df = all_df.set_index(["datetime"])
    all_df["evicted"] = all_df["id_job"].isin(evicted_df["id_job"])

    app = Dash(__name__, server=server, routes_pathname_prefix="/dash/")

    app.layout = html.Div(
        [
            html.Div(
                className="row",
                children=[
                    html.Div(
                        className="six columns",
                        children=[dcc.Graph(id="graph-with-dropdown")],
                        style=dict(width="75%"),
                    ),
                    html.Div(
                        className="six columns",
                        children=[dcc.Graph(id="graph-with-dropdown2")],
                        style=dict(width="25%"),
                    ),
                ],
                style=dict(display="flex"),
            ),
            html.Div(
                className="row",
                children=[
                    html.Div(
                        className="six columns",
                        children=[
                            dcc.Dropdown(
                                id="partition-dropdown",
                                options=[
                                    "Partition (default is all)",
                                    *all_df["partition"].unique(),
                                ],
                                value="Partition (default is all)",
                                clearable=False,
                                searchable=False,
                            )
                        ],
                        style={
                            "width": "50%",
                            "justify-content": "center",
                        },
                    ),
                    html.Div(
                        className="six columns",
                        children=[
                            dcc.Dropdown(
                                id="node-dropdown",
                                options=[
                                    "Number of Nodes (default is all)",
                                    *sorted(
                                        [
                                            int(nodes)
                                            for nodes in all_df["nodes_alloc"].unique()
                                        ]
                                    ),
                                ],
                                value="Number of Nodes (default is all)", 
                                clearable=False,
                                searchable=False,
                            )
                        ],
                        style=dict(width="50%"),
                    ),
                ],
                style=dict(display="flex"),
            ),
        ]
    )
    init_callbacks(app, df, all_df)
    return app.server


def init_callbacks(app, df, all_df):

    @app.callback(
        Output("graph-with-dropdown2", "figure"),
        [Input("node-dropdown", "value"), Input("partition-dropdown", "value")],
    )
    def update_evicted_fig(selected_nodes, selected_partition):
        if selected_nodes != "Number of Nodes (default is all)":
            filtered_df = all_df[all_df["nodes_alloc"] == selected_nodes]
        else:
            filtered_df = all_df

        if selected_partition != "Partition (default is all)":
            filtered_df = filtered_df[filtered_df["partition"] == selected_partition]
        x = ["Not Evicted", "Evicted"]

        df1 = filtered_df.groupby(["evicted"]).count().reset_index()

        fig = px.bar(
            df1,
            y=[
                100
                * filtered_df[filtered_df["evicted"] == False].size
                / filtered_df.size,
                100
                * filtered_df[filtered_df["evicted"] == True].size
                / filtered_df.size,
            ],
            x=x,
            color="evicted",
            color_discrete_map={True: "red", False: "green"},
            labels={"x": "Job Status", "y": "% of Jobs"},
        )
        fig.update_layout(transition_duration=500)

        return fig

    @app.callback(
        Output("graph-with-dropdown", "figure"),
        [Input("node-dropdown", "value"), Input("partition-dropdown", "value")],
    )
    def update_evicted_fig(selected_nodes, selected_partition):
        if selected_nodes != "Number of Nodes (default is all)":
            filtered_df = all_df[all_df["nodes_alloc"] == selected_nodes]
        else:
            filtered_df = all_df

        if selected_partition != "Partition (default is all)":
            filtered_df = filtered_df[filtered_df["partition"] == selected_partition]

        print(
            filtered_df[filtered_df["evicted"] == True]
            .groupby([pd.Grouper(freq="6H")])
            .sum(numeric_only=True)["node_hours"]
        )

        fig = px.bar(
            x=filtered_df[filtered_df["evicted"] == False]
            .groupby([pd.Grouper(freq="6H")])
            .sum(numeric_only=True)["node_hours"]
            .index,
            y=filtered_df[filtered_df["evicted"] == False]
            .groupby([pd.Grouper(freq="6H")])
            .sum(numeric_only=True)["node_hours"],
            labels={
                "x": "Date",
                "y": "Node hours",
            },
            title="Job Status",
            barmode="stack",
        )

        fig.add_bar(
            name="Evicted",
            x=filtered_df[filtered_df["evicted"] == True]
            .groupby([pd.Grouper(freq="6H")])
            .sum(numeric_only=True)["node_hours"]
            .index,
            y=filtered_df[filtered_df["evicted"] == True]
            .groupby([pd.Grouper(freq="6H")])
            .sum(numeric_only=True)["node_hours"],
        )

        fig.update_layout(transition_duration=500)

        return fig

    return app.server

我希望做的事情是可能的吗?如果是的话,是否有人可以为我强调一些文档或工作示例?

【问题讨论】:

    标签: python plotly-dash


    【解决方案1】:

    我没有你 df 所以也许你可以参考我的代码来修改你的代码:

    import pandas as pd
    import numpy as np
    import plotly.express as px
    import dash
    import dash_html_components as html
    from dash import dcc
    from dash_extensions.enrich import Input, Output, State, ServersideOutput
    import dash_bootstrap_components as dbc
    from dash.exceptions import PreventUpdate
    
    df_2 = df[(df['BAS_DT'] >= '2022-01-01')]
    df5 = df_2.pivot_table(values='USD_XC_BL',
                           index=['BAS_DT'],
                           aggfunc=np.sum).reset_index()
    fig_3 = px.bar(df5,
                   x='BAS_DT',
                   y='USD_XC_BL',
                   labels='BAS_DT',
                   hover_name='BAS_DT', color_discrete_sequence=px.colors.qualitative.Alphabet)
    
    fig_3.update_layout(xaxis_title="", yaxis_title="", plot_bgcolor='rgba(0,0,0,0)', margin=dict(l=0, r=0, t=0, b=0))
    fig_3.update_xaxes(showline=False, showgrid=False),
    fig_3.update_yaxes(showline=False, showgrid=False, separatethousands=True, tickformat=',.0f')
    
    app = dash.Dash(__name__)
    
    app.layout = html.Div([
        dbc.Row([
            dbc.Col([
                dbc.Card([
                    dbc.CardBody([
                        dbc.Row([
                            dbc.Col([
                                html.H5('Amount by Currency', style={"text-align": "center"}),
                                dcc.Loading(children=[dcc.Graph(id='histogram_map', figure=fig_3)], color='#119DFF',
                                            type='dot')
                            ], width={'size': 12, 'offset': 0, 'order': 2}, style={"text-align": "left"}),
                        ]),
                    ])
                ]),
            ], xs=6),
    
            dbc.Col([
                dbc.Card([
                    dbc.CardBody([
                        dbc.Row([
                            dbc.Col([
                                html.H5('Overdue Status', style={"text-align": "center"}),
                                dcc.Loading(children=[dcc.Graph(id='overdue_map', figure={})], color='#119DFF', type='dot')
                            ], width={'size': 12, 'offset': 0, 'order': 2}, style={"text-align": "left"}),
                        ]),
                    ])
                ]),
            ], xs=6),
        ], className='p-2 align-items-stretch')
    ])
    
    
    @app.callback(
        Output('overdue_map', 'figure'),
        Input('histogram_map', 'clickData'))
    def update_y_timeseries(clickData):
        if clickData:
            country_name = clickData['points'][0]['hovertext']
            df_3 = df[df['BAS_DT'] == country_name]
            df_4 = df_3.pivot_table(values='CLOC_CUR_XC_BL',
                                    index=['APL_DTL_NAME'],
                                    aggfunc=pd.Series.nunique).reset_index()
            fig = px.bar(df_4,
                         x='APL_DTL_NAME',
                         y='CLOC_CUR_XC_BL'
                         , color_discrete_sequence=px.colors.qualitative.Alphabet)
            fig.update_layout(xaxis_title="", yaxis_title="", plot_bgcolor='rgba(0,0,0,0)')  # plot_bgcolor='rgba(0,0,0,0)'
            fig.update_xaxes(showline=False, showgrid=False),
            fig.update_yaxes(showline=False, showgrid=False, separatethousands=True)
            fig.update_traces(width=0.3)
            return fig
        else:
            raise PreventUpdate
    
    
    if __name__ == "__main__":
        app.run_server(debug=True)
    

    我正在使用 clickData 返回 point 作为日期,然后使用这个日期来过滤数据,然后制作新的条形图。

    希望这有帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-23
      • 1970-01-01
      • 2021-10-09
      • 2018-02-18
      • 1970-01-01
      相关资源
      最近更新 更多