Plotly 中的双下拉列表

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

我想在 plotly 中创建一个双下拉列表。我应该可以选择预测的年份和条件。

这里是数据集:CollisionsForecast

我的数据集是这样的: 第一:碰撞 Collisions 我从 2013 年到 2022 年按年、月和日分组的地方 然后预测 Forecast

我已经能够用一年做到这一点,但是我不能用 2 个 dropdwon 列表做到这一点,我无法理解为什么我的代码不起作用背后的逻辑。

基本上我想添加另一个下拉列表,我可以在其中选择年份。

这是我创建一个有效下拉列表的代码:

fig = make_subplots(rows=6, cols=2, specs=[[{"secondary_y": True}, {"secondary_y": True}],
                                            [{"secondary_y": True}, {"secondary_y": True}],
                                             [{"secondary_y": True}, {"secondary_y": True}],
                                              [{"secondary_y": True}, {"secondary_y": True}],
                                               [{"secondary_y": True}, {"secondary_y": True}],
                                                [{"secondary_y": True}, {"secondary_y": True}],
                                            ])

# condition = "snow"
colors = {"Collisions": "#FFA07A",
          "tempmax": "#FF0000",
          "tempmin": "#00FF00",
          "temp": "#7EC0EE",
          "humidity": "#808080",
          "precip": "#FFC0CB",
          "snow": "#800080",
          "visibility": "#FFA500",
          }


forecast = list(df_brook_fore.columns[1:])
months = list(range(1,13))

for i, mon in enumerate(months):
    for j, condition in enumerate(forecast):
        column_idx  = 1 if i%2==0 else 2
        row_idx = i//2+1

        days = list(range(1, len(df_brook_fil_group[1]) + 1))
        fig.add_trace(go.Bar(x=days, y=df_brook_fil_group[mon], marker_color=colors["Collisions"], visible=(j == 0),
                            name='Collisions' if i == 0 else '', showlegend=True if i == 0 else False),
                            row=row_idx, col=column_idx)
        fig.add_trace(go.Scatter(x=days, y=df_brook_fore[condition][mon], visible=(j == 0),
                                marker_color=colors[condition], name=condition if i == 0 else '',
                                showlegend=True if i == 0 else False), row=row_idx, col=column_idx, secondary_y=True)

        fig.update_yaxes(title_text="Collisions", row=row_idx, col=column_idx, secondary_y=False, showgrid=False)
        fig.update_yaxes(title_text="Visibility", row=row_idx, col=column_idx, secondary_y=True, showgrid=False)

fig.update_layout(width=1000, height=1200, coloraxis=dict(colorscale='Bluered_r'), showlegend=True)
fig.update_layout(
    updatemenus=[
        dict(
            active=0,
            buttons=list([
                dict(label=condition, method="update", args=[{"visible": [((j == i*2) or (j == i*2+1)) for j in range(
                    len(forecast)*2)]}, {"title": "Normalized Collision Count by Hour for " + condition}])
                for i, condition in enumerate(forecast)
            ]),
            x=0.05, y=1.1, xanchor="left", yanchor="top"
        )
    ],
    title_text="Normalized Collision Count by Hour for " + forecast[0],
    title_x=0.5
)

fig.show()

这是我尝试创建 2 个下拉列表的代码。我很确定问题出在下拉按钮的可见选项中,但我现在不知道如何解决它。

fig = make_subplots(rows=6, cols=2, specs=[[{"secondary_y": True}, {"secondary_y": True}],
                                            [{"secondary_y": True}, {"secondary_y": True}],
                                             [{"secondary_y": True}, {"secondary_y": True}],
                                              [{"secondary_y": True}, {"secondary_y": True}],
                                               [{"secondary_y": True}, {"secondary_y": True}],
                                                [{"secondary_y": True}, {"secondary_y": True}],
                                            ])

# condition = "snow"
colors = {"Collisions": "#FFA07A",
          "tempmax": "#FF0000",
          "tempmin": "#00FF00",
          "temp": "#7EC0EE",
          "humidity": "#808080",
          "precip": "#FFC0CB",
          "snow": "#800080",
          "visibility": "#FFA500",
          }


forecast = list(df_brook_fore.columns[1:])
months = list(range(1,13))
years = list(df_brook_fore.index.get_level_values(0).unique())

for i, mon in enumerate(months):
    for k, year in enumerate(years):
        
        for j, condition in enumerate(forecast):
            column_idx  = 1 if i%2==0 else 2
            row_idx = i//2+1

            days = list(range(1, len(df_brook_fil_group[year][mon]) + 1))
            
            fig.add_trace(go.Bar(x=days, y=df_brook_fil_group[year][mon], marker_color=colors["Collisions"], visible=(j == 0) and (k==0),
                                name='Collisions' if i == 0 else '', showlegend=True if i == 0 else False),
                                row=row_idx, col=column_idx)
            fig.add_trace(go.Scatter(x=days, y=df_brook_fore.loc[year, mon][condition], visible=(j == 0),
                                    marker_color=colors[condition], name=condition if i == 0 else '',
                                    showlegend=True if i == 0 else False), row=row_idx, col=column_idx, secondary_y=True)

            fig.update_yaxes(title_text="Collisions", row=row_idx, col=column_idx, secondary_y=False, showgrid=False)
            fig.update_yaxes(title_text="Visibility", row=row_idx, col=column_idx, secondary_y=True, showgrid=False)

fig.update_layout(width=1000, height=1200, coloraxis=dict(colorscale='Bluered_r'), showlegend=True)
fig.update_layout(
    updatemenus=[
        dict(
            active=0,
            buttons=list([
                dict(label=condition, method="update", args=[{"visible": [((j == i*2) or (j == i*2+1)) for      j in range(
                    len(forecast)*2)]}, {"title": "Normalized Collision Count by Hour for " + condition}])
                for i, condition in enumerate(forecast)

            ]),
            x=0.2, y=1.1, xanchor="left", yanchor="top"
        ),

        dict(
            active=0,
            buttons=list([
                dict(label=str(year), method="update", args=[{"visible": [((j == i*2) or (j == i*2+1)) for j in range(
                    len(years)*2)]}, {"title": "Normalized Collision Count by Hour for " + str(years)}])
                for i, year in enumerate(years)
                
            ]),
            x=0.05, y=1.1, xanchor="left", yanchor="top"
        )
    ],
    title_text="Normalized Collision Count by Hour for " + str(years[0]),
    title_x=0.5
)

fig.show()

感谢您的帮助!

python callback plotly visualization plotly-dash
1个回答
0
投票

看完你的代码后,我认为使用

Dash
会完成几件事:(1)它允许两个下拉菜单同时响应,(2)通过使用回调函数,你可以选择数据你需要实时绘制。不需要在开始时绘制所有轨迹,然后根据下拉选择找出哪些应该或不应该可见(我相信你注意到了,这变得非常复杂并且很难跟踪您何时需要处理年、月和不同的预测列)。

下面是一个示例,说明您可以使用 Dash 和回调函数来处理来自两个下拉菜单的输入:

import pandas as pd
from plotly.subplots import make_subplots
import plotly.express as px
import plotly.graph_objects as go

from dash import Dash, dcc, html, Input, Output

df_brook_fil_group = pd.read_csv('colisions.csv')
df_brook_fil_group = df_brook_fil_group.set_index(['Year','Month','Day'])

df_brook_fore = pd.read_csv('forecast.csv')
df_brook_fore = df_brook_fore.set_index(['Year','Month','Day'])

forecast = list(df_brook_fore.columns[1:])

fig = make_subplots(rows=6, cols=2, specs=[[{"secondary_y": True}, {"secondary_y": True}],
                                            [{"secondary_y": True}, {"secondary_y": True}],
                                             [{"secondary_y": True}, {"secondary_y": True}],
                                              [{"secondary_y": True}, {"secondary_y": True}],
                                               [{"secondary_y": True}, {"secondary_y": True}],
                                                [{"secondary_y": True}, {"secondary_y": True}],
                                            ])

# condition = "snow"
colors = {"Collisions": "#FFA07A",
          "tempmax": "#FF0000",
          "tempmin": "#00FF00",
          "temp": "#7EC0EE",
          "humidity": "#808080",
          "precip": "#FFC0CB",
          "snow": "#800080",
          "visibility": "#FFA500",
          }

app = Dash(__name__)
app.layout = html.Div(
    [
        html.Div(
            [
                dcc.Dropdown(
                    id="year-dropdown",
                    options=[2014, 2015],
                    value=2014,
                    placeholder="Select year",
                    style={"display": "inline-block", "width": "180px"},
                ),
                dcc.Dropdown(
                    id="forecast-dropdown",
                    options=forecast,
                    value="tempmin",
                    placeholder="Select your forecast column",
                    style={"display": "inline-block", "width": "180px"},
                ),
            ],
            style={"padding": "80px"},
        ),
        dcc.Graph(figure=fig, id='scatter-bar-chart')
    ]
)


@app.callback(
    Output('scatter-bar-chart', 'figure'),
    Input('year-dropdown', 'value'),
    Input('forecast-dropdown', 'value'),
)
def update_output(year, forecast):

    df_brook_fil_group_subset = df_brook_fil_group.loc[year,:,:]
    df_brook_fore_subset = df_brook_fore.loc[year,:,:]
    months = list(range(1,13))

    ## create subplots based on how many months there are
    fig = make_subplots(rows=6, cols=2, specs=[[{"secondary_y": True}, {"secondary_y": True}],
                                            [{"secondary_y": True}, {"secondary_y": True}],
                                             [{"secondary_y": True}, {"secondary_y": True}],
                                              [{"secondary_y": True}, {"secondary_y": True}],
                                               [{"secondary_y": True}, {"secondary_y": True}],
                                                [{"secondary_y": True}, {"secondary_y": True}],
                                            ])
    
    row, col = 1, 1

    for i, mon in enumerate(months):
        df_brook_fil_group_month = df_brook_fil_group_subset.loc[mon,:] 
        df_brook_fore_month = df_brook_fore_subset.loc[mon,:]

        df_brook_fil_group_days = df_brook_fil_group_month.index.get_level_values('Day')
        df_brook_fore_month_days = df_brook_fore_month.index.get_level_values('Day')

        ## use legendgroups to ensure entries only show up once
        fig.add_trace(go.Bar(x=df_brook_fil_group_days, y=df_brook_fil_group_month['COLLISION_ID'], 
                                marker_color=colors["Collisions"],
                                showlegend=True if i == 0 else False,
                                name='Collisions', legendgroup='Collisions'),
                                row=row, col=col)
        fig.add_trace(go.Scatter(x=df_brook_fore_month_days, y=df_brook_fore_month[forecast],
                                marker_color=colors[forecast], name=forecast if i == 0 else '',
                                showlegend=True if i == 0 else False,
                                legendgroup=forecast), 
                                row=row, col=col, secondary_y=True)

        fig.update_yaxes(title_text="Collisions", row=row, col=col, secondary_y=False, showgrid=False)
        fig.update_yaxes(title_text="Visibility", row=row, col=col, secondary_y=True, showgrid=False)
        fig.update_layout(
            width=1000, height=1200, 
            coloraxis=dict(colorscale='Bluered_r'), showlegend=True,
            title_text="Normalized Collision Count by Hour for " + str(year),
            title_x=0.5
        )
        
        # iterate through (1,1),(1,2),(2,1),(2,2),(3,1),(3,2), ... to place the bar + scatter traces
        if i % 2 == 0:
            col += 1
        else:
            row += 1
            if col == 1:
                col = 2
            if col == 2:
                col = 1
        
    return fig


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

破折号应用程序响应年份和预测类型的下拉列表:

注意:由于文件大小,我无法显示应用程序的所有 6 行

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.