将 Dash 与 Plotly 图形对象和日期选择器结合使用,在单个图中绘制和更新多个数据轨迹,默认情况下包含完整数据范围

问题描述 投票:0回答:1

使用 Dash 的新功能,需要使用日期选择器组件在单个图中绘制多个绘图轨迹。寻找展示如何执行以下操作的示例:

  1. 在选择任何日期范围之前加载时自动绘制默认的完整数据范围。
  2. 选择日期范围后更新单个图框(两条迹线)。

现在日期选择器可以工作,但在选择日期范围之前绘图是空白的。 此外,选择日期范围后,绘图将覆盖所选数据下方的完整数据。

import pandas as pd
from dash import Dash, html, dcc 
from dash.exceptions import PreventUpdate
import plotly.graph_objects as go
from dash.dependencies import Input, Output
from plotly.subplots import make_subplots

# initialize the dash app as 'app'
app = Dash(__name__)

population_1=1e7+50*np.arange(61)
population_2=1e8+5*np.arange(61)**2
test_df=pd.DataFrame(data={'pop 1':population_1, 'pop 2': population_2})

test_df.index=pd.date_range(start='2000-01-01', end='2000-03-01')

# use specs parameter in make_subplots function
# to create secondary y-axis
fig = make_subplots(specs=[[{"secondary_y": True}]])

# plot a scatter chart by specifying the x and y values
# Use add_trace function to specify secondary_y axes.
fig.add_trace(
    go.Scatter(x=test_df.index, y=test_df['pop 1'], name="pop 1"),
    secondary_y=False)
 
# Use add_trace function and specify secondary_y axes = True.
fig.add_trace(
    go.Scatter(x=test_df.index, y=test_df['pop 2'], name="pop 2"),
    secondary_y=True,)

beginning_date=test_df.index[0]
ending_date=test_df.index[-1]

# set up the app layout
app.layout = html.Div(children=
                    [
                    html.H1(children=['Test Daframe Dashboard']),
                    html.Div(children=['Population plotting with year picker']),

                    dcc.DatePickerRange(
                        id='my-date-picker-range',
                        min_date_allowed=beginning_date,
                        max_date_allowed=ending_date
                    ),
                    dcc.Graph(id='population-plot',figure={}),                    
                    ] 
                    )

@app.callback(
    Output('population-plot', 'figure'),
    Input('my-date-picker-range', 'start_date'),
    Input('my-date-picker-range', 'end_date'))

def update_output(start_date, end_date):
    print (start_date, end_date)
    
    if not start_date or not end_date:
        raise PreventUpdate
    else:
        output_selected_df=test_df.loc[(test_df.index>=start_date)&(test_df.index<=end_date),:]
        fig.add_trace(
        go.Scatter(x=output_selected_df.index, y=output_selected_df['pop 1'], name="pop 1"),
        secondary_y=False)
 
        # Use add_trace function and specify secondary_y axes = True.
        fig.add_trace(
            go.Scatter(x=output_selected_df.index, y=output_selected_df['pop 2'], name="pop 2"),
            secondary_y=True,)
        return fig


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

plotly-dash
1个回答
0
投票

解决此问题的一种方法是创建一个函数来管理图形创建,然后将其用于初始加载和回调。您可以在函数外部按日期过滤数据帧,也可以将日期参数传递到函数并在内部进行过滤。

我创建了

create_figure
来演示这个解决方案。在您的示例中,您正在过滤回调内的
test_df
,因此该函数只需将数据帧作为参数即可。

def create_figure(df):
    fig = make_subplots(specs=[[{"secondary_y": True}]])
    fig.add_trace(
        go.Scatter(x=df.index, y=df["pop 1"], name="pop 1"), secondary_y=False
    )
    fig.add_trace(
        go.Scatter(x=df.index, y=df["pop 2"], name="pop 2"),
    secondary_y=True,
    )
    return fig

当您最初创建 dcc.Graph 时,您可以使用该函数创建图形并将完整的数据帧传递给该函数。

dcc.Graph(id="population-plot", figure=create_figure(test_df)),

布局初始化时,图形将接收图形。要防止回调在页面加载时触发,请将

prevent_initial_call=True
添加到回调参数中。

最后,在回调中调用

create_figure(output_selected_df)
来创建过滤后的图表。

enter image description here

完整代码如下:

import pandas as pd
import numpy as np
from dash import Dash, html, dcc
from dash.exceptions import PreventUpdate
import plotly.graph_objects as go
from dash.dependencies import Input, Output
from plotly.subplots import make_subplots

# initialize the dash app as 'app'
app = Dash(__name__)

population_1 = 1e7 + 50 * np.arange(61)
population_2 = 1e8 + 5 * np.arange(61) ** 2
test_df = pd.DataFrame(data={"pop 1": population_1, "pop 2": population_2})
test_df.index = pd.date_range(start="2000-01-01", end="2000-03-01")
beginning_date = test_df.index[0]
ending_date = test_df.index[-1]


def create_figure(df):
    fig = make_subplots(specs=[[{"secondary_y": True}]])
    fig.add_trace(
        go.Scatter(x=df.index, y=df["pop 1"], name="pop 1"), secondary_y=False
    )
    fig.add_trace(
        go.Scatter(x=df.index, y=df["pop 2"], name="pop 2"), secondary_y=True,
    )
    return fig


# set up the app layout
app.layout = html.Div(
    children=[
        html.H1(children=["Test Dataframe Dashboard"]),
        html.Div(children=["Population plotting with year picker"]),
        dcc.DatePickerRange(
            id="my-date-picker-range",
            min_date_allowed=beginning_date,
            max_date_allowed=ending_date,
        ),
        dcc.Graph(id="population-plot", figure=create_figure(test_df)),
    ]
)


@app.callback(
    Output("population-plot", "figure"),
    Input("my-date-picker-range", "start_date"),
    Input("my-date-picker-range", "end_date"),
    prevent_initial_call=True
)
def update_output(start_date, end_date):
    print(start_date, end_date)

    if not start_date or not end_date:
        raise PreventUpdate
    else:
        output_selected_df = test_df.loc[
            (test_df.index >= start_date) & (test_df.index <= end_date), :
        ]
        return create_figure(output_selected_df)


if __name__ == "__main__":
    app.run(debug=True)
© www.soinside.com 2019 - 2024. All rights reserved.