Plotly中按分类字段为单条折线设置红绿分段颜色的方法
问题描述
现有包含正弦形态数值的数据集,包含tag、num1、num1_color、num2、num2_color共5列,需要基于Plotly绘制折线图:
- x轴映射
tag列 - y轴分别映射
num1、num2列 - 折线颜色规则:
num1折线颜色随num1_color列值动态变化,num2折线颜色随num2_color列值动态变化,其中G对应绿色、R对应红色(颜色判定规则为当前值较前值上涨标G、下跌标R) - 预期效果:

可复现基础代码
样例数据构造
import pandas as pd import numpy as np # 构造样例DataFrame ty = pd.DataFrame() ty['tag'] = [1,2,3,4,5,6,7,8,9,10,11] ty['num1'] = [0.0, 0.9096319953545183, 0.7557495743542583, -0.2817325568414294, -0.9898214418809327, -0.5406408174555974, 0.5406408174555971, 0.9898214418809328, 0.2817325568414299, -0.7557495743542577, -0.9096319953545183] ty['num1_color'] = np.where(ty['num1'] >ty['num1'].shift(1) , 'G' , 'R') ty['num2'] = [0.0, 0.9898214418809328, -0.2817325568414294, -0.9096319953545186, 0.5406408174555971, 0.7557495743542594, -0.7557495743542577, -0.5406408174555977, 0.9096319953545179, 0.28173255684143184, -0.9898214418809322] ty['num2_color'] = np.where(ty['num2'] >ty['num2'].shift(1) , 'G' , 'R')
运行后数据预览如下:
| tag | num1 | num1_color | num2 | num2_color |
|---|---|---|---|---|
| 1 | 0.000000 | R | 0.000000 | R |
| 2 | 0.909632 | G | 0.989821 | G |
| 3 | 0.755750 | R | -0.281733 | R |
| 4 | -0.281733 | R | -0.909632 | R |
| 5 | -0.989821 | R | 0.540641 | G |
| 6 | -0.540641 | G | 0.755750 | G |
| 7 | 0.540641 | G | -0.755750 | R |
| 8 | 0.989821 | G | -0.540641 | G |
| 9 | 0.281733 | R | 0.909632 | G |
| 10 | -0.755750 | R | 0.281733 | R |
| 11 | -0.909632 | R | -0.989821 | R |
初始绘图代码
初始代码仅支持为整条折线设置单一固定颜色,无法实现分段变色效果:
import plotly import plotly.express as px import plotly.graph_objects as go from plotly.subplots import make_subplots fig = go.Figure() fig = make_subplots(specs=[{"secondary_y": True}]) x = ty['tag'];y1=ty['num1'];y2=ty['num2'] fig.add_trace(go.Scatter(x=x, y=y1, mode='lines', marker_color='blue', name='macd'), secondary_y=False) fig.add_trace(go.Scatter(x=x, y=y2, mode='lines', marker_color='red', name='signal'), secondary_y=False) fig.show()
改造实现方案
Plotly单条Scatter轨迹不支持单条折线分段设置颜色,实现逻辑为:按颜色标签将折线拆分为多个连续同色线段,每个线段单独作为一条轨迹添加,同系列同色线段统一绑定图例组,保证点击图例可同时隐藏/显示同系列所有线段,和单条轨迹的交互体验一致。
改造后完整可运行代码:
import pandas as pd import numpy as np import plotly.graph_objects as go from plotly.subplots import make_subplots # 复用样例数据构造逻辑 ty = pd.DataFrame() ty['tag'] = [1,2,3,4,5,6,7,8,9,10,11] ty['num1'] = [0.0, 0.9096319953545183, 0.7557495743542583, -0.2817325568414294, -0.9898214418809327, -0.5406408174555974, 0.5406408174555971, 0.9898214418809328, 0.2817325568414299, -0.7557495743542577, -0.9096319953545183] ty['num1_color'] = np.where(ty['num1'] >ty['num1'].shift(1) , 'G' , 'R') ty['num2'] = [0.0, 0.9898214418809328, -0.2817325568414294, -0.9096319953545186, 0.5406408174555971, 0.7557495743542594, -0.7557495743542577, -0.5406408174555977, 0.9096319953545179, 0.28173255684143184, -0.9898214418809322] ty['num2_color'] = np.where(ty['num2'] >ty['num2'].shift(1) , 'G' , 'R') # 颜色映射规则 color_map = {'G': 'green', 'R': 'red'} def add_segment_line(fig, df, x_col, y_col, color_col, series_name, color_map, secondary_y=False): """ 按颜色标签分段绘制折线,同系列线段共享图例交互 :param fig: Plotly画布对象 :param df: 输入数据集 :param x_col: x轴对应列名 :param y_col: y轴对应列名 :param color_col: 颜色标签对应列名 :param series_name: 系列名称(用于图例展示) :param color_map: 颜色标签到实际色值的映射字典 :param secondary_y: 是否绘制在次坐标轴 """ first_trace = True # 遍历所有相邻点对,两点间线段颜色由后一个点的颜色标签决定 for i in range(1, len(df)): segment_x = [df.loc[i-1, x_col], df.loc[i, x_col]] segment_y = [df.loc[i-1, y_col], df.loc[i, y_col]] line_color = color_map[df.loc[i, color_col]] fig.add_trace( go.Scatter( x=segment_x, y=segment_y, mode='lines', line=dict(color=line_color, width=2), name=series_name, legendgroup=series_name, showlegend=True if first_trace else False ), secondary_y=secondary_y ) first_trace = False # 创建画布并绘图 fig = make_subplots(specs=[{"secondary_y": True}]) add_segment_line(fig, ty, x_col='tag', y_col='num1', color_col='num1_color', series_name='num1', color_map=color_map, secondary_y=False) add_segment_line(fig, ty, x_col='tag', y_col='num2', color_col='num2_color', series_name='num2', color_map=color_map, secondary_y=False) # 布局调整 fig.update_layout( title='正弦形态数据分段着色折线图', xaxis_title='tag', yaxis_title='数值', legend_title='数据系列' ) fig.show()
代码说明
- 线段绘制以相邻两个点为最小单元,线段颜色取终点对应的颜色标签,完全匹配“当前值相对前值涨跌决定颜色”的规则
- 通过
legendgroup参数绑定同系列所有线段,图例交互逻辑和单条折线完全一致 - 线段宽度、颜色色值、坐标轴配置可根据实际需求调整参数
内容的提问来源于stack exchange,提问作者Nabi Shaikh
相关产品推荐
相关产品推荐

