Plotly:如何根据条件为两条线之间的填充着色?

Posted

技术标签:

【中文标题】Plotly:如何根据条件为两条线之间的填充着色?【英文标题】:Plotly: How to color the fill between two lines based on a condition? 【发布时间】:2021-02-20 17:53:04 【问题描述】:

我想在我的 Plotly 图表上的黑线和蓝线之间添加填充颜色。我知道这可以通过 Plotly 完成,但我不确定如何根据条件用两种颜色填充图表。

蓝色背景的图表是我的 Plotly 图表。我想让它看起来像白色背景的图表。 (忽略白色图表上的红色和绿色条)

我希望它通过的条件是:

如果黑线在蓝线上方,则将两条线之间的区域填充为绿色。

如果黑线在蓝线下方,则将两条线之间的区域填充为红色。

如何用 Plotly 做到这一点?如果 Plotly 无法做到这一点,是否可以使用其他支持 Python 的绘图工具来完成。

【问题讨论】:

【参考方案1】:

出于多种原因(如果您有兴趣,我愿意进一步解释)最好的方法似乎是每次您的平均值相互交叉时向 go.Figure() 对象添加两条轨迹,然后定义使用fill='tonexty' 填充第二个跟踪使用:

for df in dfs:
    fig.add_traces(go.Scatter(x=df.index, y = df.ma1,
                              line = dict(color='rgba(0,0,0,0)')))
    
    fig.add_traces(go.Scatter(x=df.index, y = df.ma2,
                              line = dict(color='rgba(0,0,0,0)'),
                              fill='tonexty', 
                              fillcolor = fillcol(df['label'].iloc[0])))

fillcolor 是下面完整的 sn-p 中描述的简单自定义函数。我已经使用How to split a dataframe each time a string value changes in a column? 中描述的方法在每次您的平均值相互交叉时在数据框中产生必要的拆分。

情节

完整代码:

import plotly.graph_objects as go
import numpy as np

import pandas as pd
from datetime import datetime
pd.options.plotting.backend = "plotly"

# sample data
df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/finance-charts-apple.csv')
df.index = df.Date
df = df[['AAPL.Close', 'mavg']]
df['mavg2'] = df['AAPL.Close'].rolling(window=50).mean()
df.columns = ['y', 'ma1', 'ma2']
df=df.tail(250).dropna()
df1 = df.copy()

# split data into chunks where averages cross each other
df['label'] = np.where(df['ma1']>df['ma2'], 1, 0)
df['group'] = df['label'].ne(df['label'].shift()).cumsum()
df = df.groupby('group')
dfs = []
for name, data in df:
    dfs.append(data)

# custom function to set fill color
def fillcol(label):
    if label >= 1:
        return 'rgba(0,250,0,0.4)'
    else:
        return 'rgba(250,0,0,0.4)'

fig = go.Figure()

for df in dfs:
    fig.add_traces(go.Scatter(x=df.index, y = df.ma1,
                              line = dict(color='rgba(0,0,0,0)')))
    
    fig.add_traces(go.Scatter(x=df.index, y = df.ma2,
                              line = dict(color='rgba(0,0,0,0)'),
                              fill='tonexty', 
                              fillcolor = fillcol(df['label'].iloc[0])))

# include averages
fig.add_traces(go.Scatter(x=df1.index, y = df1.ma1,
                          line = dict(color = 'blue', width=1)))

fig.add_traces(go.Scatter(x=df1.index, y = df1.ma2,
                          line = dict(color = 'red', width=1)))

# include main time-series
fig.add_traces(go.Scatter(x=df1.index, y = df1.y,
                          line = dict(color = 'black', width=2)))

fig.update_layout(showlegend=False)
fig.show()

【讨论】:

当每个值对的标签交替出现时,这不起作用。换句话说:在我的数据集中,这些组大部分时间只包含一个值。然后,Plotly 根本不会绘制填充图。

以上是关于Plotly:如何根据条件为两条线之间的填充着色?的主要内容,如果未能解决你的问题,请参考以下文章

“如何在 Line-plot 中显示两条线的数据点之间的差异值?”

Plotly R中的可移动线

Python Plotly Express:如何有条件地填充区域图?

Plotly:当 2 行相互靠近时如何创建指针

计算 3D 中两条线(线段)之间的最短距离

怎样去掉visio中两条线之间的凸点