如何在Plotly中实现类型筛选与数据列切换的多过滤按钮?
Plotly 多交互按钮实现:类型筛选+指标切换
需求
- 两组交互按钮:
- 按数据类型(A、B)筛选,支持显示所有类型或单一类型
- 切换显示指标:月度增长率(
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()
关键实现说明
- 初始数据加载:用
color='type'让Plotly自动按类型分组绘制,同时加载两个指标的全量数据,后续通过按钮控制可见性或更新数据 - 类型筛选逻辑:通过解析每个曲线的名称(格式如
growth_monthly=A)判断是否显示对应类型的曲线,用restyle方法直接修改可见性 - 指标切换逻辑:使用
restyle方法直接更新每个曲线的y值和name,实现不同指标的无缝切换 - 扩展支持:若要添加12个月滚动平均值,只需在数据中新增对应列,然后在指标切换按钮中添加新的按钮项,更新对应的
y值和name即可
内容的提问来源于stack exchange,提问作者vossi
相关产品推荐
相关产品推荐

