Plotly绘制折线图时实现线条交叉处自动更改颜色
需求说明
现有包含日期列、S1与S2两个数值数据序列的pandas DataFrame,需使用Plotly绘制折线图,实现两条数据序列交叉时,自动更改对应位置的线条颜色。
初期尝试与存在的问题
最初的实现逻辑为逐行判断S1与S2的大小关系生成颜色列表,传入go.Scatter的line.color参数,代码如下:
import plotly.graph_objects as go from plotly.subplots import make_subplots data = {'Date': ['1.1.2020', '2.1.2020', '3.1.2020', '4.1.2020', '5.1.2020'], 'S1': [20, 21, 19, 18, 20], 'S2': [10, 11, 30, 18, 10]} df = pd.DataFrame(data) df['color']= df.apply(lambda row: 'black' if row['S1'] >= row['S2'] else 'red', axis=1) fig = make_subplots(rows=1, cols=1, vertical_spacing=0.05, shared_xaxes=True) fig.add_trace(go.Scatter( x=df['Date'], y=df['S1'], line=dict(color='blue')), row=1, col=1) fig.add_trace(go.Scatter( x=df['Date'], y=df['S2'], line=dict(color=list(df['color']))), row=1, col=1) fig.show()
该代码运行后未达到预期效果,无法在交叉处正确切换线条颜色。后续将测试数据集扩大到10条记录验证其他方案时,又出现交叉点位之间存在多余红色连线的问题,测试数据集如下:
data = {'Date': ['1.1.2020', '2.1.2020', '3.1.2020', '4.1.2020', '5.1.2020', '6.1.2020', '7.1.2020', '8.1.2020', '9.1.2020', '10.1.2020'], 'S1': [20, 21, 19, 18, 20, 19, 18, 20, 20, 20], 'S2': [10, 11, 30, 18, 10, 10, 17, 30, 20, 10]}
最终可行方案
采用分层绘制轨迹的思路实现效果:
- 第一层绘制固定为蓝色的S1完整折线
- 第二层绘制固定为黑色的S2基础折线
- 第三层提取S1小于S2的交叉区间及前后相邻点位的S2数值,绘制红色线段覆盖对应交叉段
完整可运行代码如下:
import plotly.graph_objects as go from plotly.subplots import make_subplots import pandas as pd data = {'Date': ['1.1.2020', '2.1.2020', '3.1.2020', '4.1.2020', '5.1.2020', '6.1.2020', '7.1.2020', '8.1.2020', '9.1.2020', '10.1.2020'], 'S1': [20, 21, 19, 18, 20, 19, 18, 20, 20, 20], 'S2': [10, 11, 30, 18, 10, 10, 17, 30, 20, 10]} df = pd.DataFrame(data) df['crossing']= df.loc[(df.S1 < df.S2) | (df.S1.shift(1) < df.S2.shift(1)) | (df.S1.shift(-1) < df.S2.shift(-1)), 'S2'] fig = go.Figure() fig.add_trace(go.Scatter( x=df['Date'], y=df['S1'], line=dict(color='blue'))) fig.add_trace(go.Scatter( x=df['Date'], y=df['S2'], line=dict(color='black'))) fig.add_trace(go.Scatter( x=df['Date'], y=df['crossing'], line=dict(color='red'))) fig.show()
内容的提问来源于stack exchange,提问作者khrizz
相关产品推荐
相关产品推荐

