Plotly的add_vline注释垂直居中及添加可交互图例实现问题
实现代码
import plotly.express as px import pandas as pd import numpy as np df = pd.DataFrame({'height': [712, 712, 716, 716, 718, np.nan, np.nan, np.nan, np.nan, np.nan], 'moisture ': [0.06, 0.19, 0.18, 0.17, 0.18, np.nan, np.nan, np.nan, np.nan, np.nan], 'tasks': ['water', None, None, 'prune', None, None, 'position', None, 'prune', None], 'weather': [None, 'humid', None, None, 'wet', None, None, None, None, 'hot']}, index=['2020-01-04', '2020-01-05', '2020-01-06', '2020-01-07', '2020-01-08', '2020-01-09', '2020-01-10', '2020-01-11', '2020-01-12', '2020-01-13']) # 转换索引为datetime类型,适配Plotly时间轴规则 df.index = pd.to_datetime(df.index) df.index.name = 'date' fig = px.line(df, y="height") # 计算Y轴数值范围,确定注释竖直中点坐标 y_min = df['height'].min() y_max = df['height'].max() y_mid = (y_min + y_max) / 2 # 处理tasks对应红色参考线 task_dates = df.loc[~df["tasks"].isna()].index for i, x in enumerate(task_dates): # 用scatter trace绘制垂直线,支持图例交互 fig.add_scatter( x=[x, x], y=[y_min, y_max], mode='lines', line=dict(width=1, dash='dash', color='red'), legendgroup='tasks', name='任务标记', # 仅第一条同类型线显示图例,避免出现重复条目 showlegend=True if i == 0 else False ) # 添加中点位置注释 fig.add_annotation( x=x, y=y_mid, text=df.loc[x, 'tasks'], showarrow=False, bgcolor='white', bordercolor='red', legendgroup='tasks' ) # 处理weather对应蓝色参考线 weather_dates = df.loc[~df["weather"].isna()].index for i, x in enumerate(weather_dates): fig.add_scatter( x=[x, x], y=[y_min, y_max], mode='lines', line=dict(width=1, dash='dash', color='blue'), legendgroup='weather', name='天气标记', showlegend=True if i == 0 else False ) fig.add_annotation( x=x, y=y_mid, text=df.loc[x, 'weather'], showarrow=False, bgcolor='white', bordercolor='blue', legendgroup='weather' ) fig.show()
关键修改说明
- 放弃原生
add_vline方法:该方法生成的是布局层级的形状,无法绑定图例实现交互隐藏,改用scattertrace绘制垂直线,天然支持图例关联 - 注释固定中点:提前计算Y轴数值的上下限,取平均值作为所有注释的Y坐标,实现所有参考线注释统一居中
- 分组交互:同类型的线和注释绑定相同的
legendgroup参数,点击图例对应条目时,同组的所有线和注释会同时隐藏/显示
内容的提问来源于stack exchange,提问作者Diop Chopra
相关产品推荐
相关产品推荐

