You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Plotly中实现类型筛选与数据列切换的多过滤按钮?

Plotly 多交互按钮实现:类型筛选+指标切换

需求

  • 两组交互按钮:
    1. 按数据类型(A、B)筛选,支持显示所有类型或单一类型
    2. 切换显示指标:月度增长率(growth_monthly)、6个月滚动平均值(6_month_rolling_average),后续可扩展12个月滚动平均值
  • 初始默认显示所有类型的月度增长率

示例数据

import pandas as pd
import numpy as np

df = pd.DataFrame({
    'date': ['2018-01-01', '2018-02-01', '2018-03-01', '2018-04-01', '2018-05-01', '2018-06-01', '2018-07-01', '2018-08-01', '2018-09-01', '2018-10-01', '2018-11-01', '2018-12-01', '2019-01-01', '2019-02-01', '2019-03-01', '2019-04-01', '2019-05-01', '2019-06-01', '2019-07-01', '2019-08-01', '2019-09-01', '2019-10-01', '2019-11-01', '2019-12-01', '2018-01-01', '2018-02-01', '2018-03-01', '2018-04-01', '2018-05-01', '2018-06-01', '2018-07-01', '2018-08-01', '2018-09-01', '2018-10-01', '2018-11-01', '2018-12-01', '2019-01-01', '2019-02-01', '2019-03-01', '2019-04-01', '2019-05-01', '2019-06-01', '2019-07-01', '2019-08-01', '2019-09-01', '2019-10-01', '2019-11-01', '2019-12-01'],
    'type': ['A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B'],
    'total_transactions': [3848, 8137, 3329, 7896, 5832, 3766, 5864, 7411, 7908, 7579, 7386, 7583, 6593, 5506, 7091, 6422, 8724, 4268, 7052, 6231, 5329, 2581, 4248, 2602, 3854, 8231, 5238, 8678, 1580, 4596, 4334, 3872, 5360, 5993, 8358, 8664, 6538, 7030, 7177, 9669, 7506, 4146, 5137, 7325, 9721, 3905, 3497, 5030],
    'growth_monthly': [np.nan, 111.46, -59.09, 137.19, -26.14, -35.43, 55.71, 26.38, 6.71, -4.16, -2.55, 2.67, -13.06, -16.49, 28.79, -9.43, 35.85, -51.08, 65.23, -11.64, -14.48, -51.57, 64.59, -38.75, np.nan, 113.57, -36.36, 65.67, -81.80, 190.89, -5.7, -10.66, 38.43, 11.81, 39.46, 3.66, -24.54, 7.53, 2.09, 34.72, -22.37, -44.76, 23.9, 42.59, 32.71, -59.83, -10.45, 43.84],
    '6_month_rolling_average': [np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, 30.62, 16.44, 27.4, 3.84, 7.78, 14.13, 2.66, -4.48, -0.8, -1.68, 4.72, -4.24, 8.81, 9.62, 2.41, -4.62, 0.17, 2.23, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, 41.05, 20.34, 32.81, 23.83, 44.04, 12.83, 9.69, 12.72, 6.67, 10.49, 0.18, -7.89, 0.18, 6.03, 11.13, -4.63, -2.64, 12.13]
})

完整实现代码

import plotly.express as px
import plotly.graph_objects as go

# 初始化图表:按类型分组绘制两个指标,默认只显示月度增长率
fig = px.line(df, x='date', y=['growth_monthly', '6_month_rolling_average'], 
              color='type', color_discrete_map={'A': '#1f77b4', 'B': '#ff7f0e'})

# 基础布局设置
fig.update_yaxes(title='Growth (in %)')
fig.update_xaxes(title=None)
fig.update_layout(
    title='Growth',
    margin={'t': 100, 'r': 10, 'l': 50, 'b': 50},
    legend=dict(
        xanchor='left', x=1.01, yanchor='top', y=1.0, 
        title=None, bgcolor='rgba(0,0,0,0)', orientation='v', 
        font=dict(size=10, color="black")
    ),
    # 两组交互按钮
    updatemenus=[
        # 第一组:类型筛选按钮
        go.layout.Updatemenu(
            active=0,
            showactive=True,
            x=-0.24, y=1.12,
            xanchor='left', yanchor='top',
            buttons=[
                # 显示所有类型
                dict(
                    label='All',
                    method='restyle',
                    args=[{'visible': [True]*len(fig.data)}, {'showlegend': True}]
                ),
                # 显示类型A
                dict(
                    label='A',
                    method='restyle',
                    args=[{'visible': [d.name.split('=')[-1] == 'A' for d in fig.data]}, {'showlegend': True}]
                ),
                # 显示类型B
                dict(
                    label='B',
                    method='restyle',
                    args=[{'visible': [d.name.split('=')[-1] == 'B' for d in fig.data]}, {'showlegend': True}]
                )
            ]
        ),
        # 第二组:指标切换按钮
        go.layout.Updatemenu(
            active=0,
            showactive=True,
            x=-0.24, y=1.04,
            xanchor='left', yanchor='top',
            buttons=[
                # 切换到月度增长率
                dict(
                    label='月度增长率',
                    method='restyle',
                    args=[
                        {'y': [df[df['type'] == 'A']['growth_monthly'], df[df['type'] == 'B']['growth_monthly']]},
                        {'name': ['growth_monthly=A', 'growth_monthly=B']}
                    ]
                ),
                # 切换到6个月滚动平均值
                dict(
                    label='6个月滚动平均值',
                    method='restyle',
                    args=[
                        {'y': [df[df['type'] == 'A']['6_month_rolling_average'], df[df['type'] == 'B']['6_month_rolling_average']]},
                        {'name': ['6_month_rolling_average=A', '6_month_rolling_average=B']}
                    ]
                )
            ]
        )
    ],
    # 按钮标签注释
    annotations=[
        dict(text="类型筛选:", x=-0.24, xref="paper", y=1.14, yref="paper", align="left", showarrow=False),
        dict(text="指标切换:", x=-0.24, xref="paper", y=1.06, yref="paper", align="left", showarrow=False)
    ]
)

# 设置初始状态:隐藏所有滚动平均值曲线
for i, trace in enumerate(fig.data):
    if '6_month_rolling_average' in trace.name:
        fig.data[i].visible = False

fig.show()

关键实现说明

  1. 初始数据加载:用color='type'让Plotly自动按类型分组绘制,同时加载两个指标的全量数据,后续通过按钮控制可见性或更新数据
  2. 类型筛选逻辑:通过解析每个曲线的名称(格式如growth_monthly=A)判断是否显示对应类型的曲线,用restyle方法直接修改可见性
  3. 指标切换逻辑:使用restyle方法直接更新每个曲线的y值和name,实现不同指标的无缝切换
  4. 扩展支持:若要添加12个月滚动平均值,只需在数据中新增对应列,然后在指标切换按钮中添加新的按钮项,更新对应的y值和name即可

内容的提问来源于stack exchange,提问作者vossi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 23:12:01