Plotly:如何根据条件为两条线之间的填充着色? [英] Plotly: How to color the fill between two lines based on a condition?

查看:119
本文介绍了Plotly:如何根据条件为两条线之间的填充着色?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

我希望它通过的条件是:

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

如果黑线低于蓝线,则将两条线之间的区域填充为红色.

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

解决方案

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

对于dfs中的df:fig.add_traces(go.Scatter(x=df.index, y = df.ma1,行 = 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)'),填充='音调',fillcolor = fillcol(df['label'].iloc[0])))

fillcolor 是下面完整代码段中描述的简单自定义函数.我使用了

完整代码:

import plotly.graph_objects as go将 numpy 导入为 np将熊猫导入为 pd从日期时间导入日期时间pd.options.plotting.backend = "plotly";# 样本数据df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/finance-charts-apple.csv')df.index = df.Datedf = 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()# 将数据分成多个块,其中平均值相互交叉df['label'] = np.where(df['ma1']>df['ma2'], 1, 0)df['group'] = df['label'].ne(df['label'].shift()).cumsum()df = df.groupby('组')dfs = []对于名称,df 中的数据:dfs.append(数据)# 自定义函数来设置填充颜色定义填充(标签):如果标签 >= 1:返回'RGBA(0,250,0,0.4)'别的:返回'RGBA(250,0,0,0.4)'fig = go.Figure()对于 dfs 中的 df:fig.add_traces(go.Scatter(x=df.index, y = df.ma1,行 = 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)'),填充='音调',fillcolor = fillcol(df['label'].iloc[0])))# 包括平均值fig.add_traces(go.Scatter(x=df1.index, y = df1.ma1,线 = dict(颜色 = '蓝色', 宽度 = 1)))fig.add_traces(go.Scatter(x=df1.index, y = df1.ma2,行 = dict(颜色 = '红色', 宽度 = 1)))# 包括主要时间序列fig.add_traces(go.Scatter(x=df1.index, y = df1.y,线 = dict(颜色 = '黑色', 宽度 = 2)))fig.update_layout(showlegend=False)图.show()

I want to add a fill colour between the black and blue line on my Plotly chart. I am aware this can be accomplished already with Plotly but I am not sure how to fill the chart with two colours based on conditions.

The chart with the blue background is my Plotly chart. I want to make it look like the chart with the white background. (Ignore the red and green bars on the white chart)

The conditions I want it to pass is:

Fill the area between the two lines GREEN, if the black line is above the blue line.

Fill the area between the two lines RED, if the black line is below the blue line.

How can this be done with Plotly? If this is not possible with Plotly can it be accomplished with other graphing tools that work with Python.

解决方案

For a number of reasons (that I'm willing to explain further if you're interested) the best approach seems to be to add two traces to a go.Figure() object for each time your averages cross eachother, and then define the fill using fill='tonexty' for the second trace using:

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 is a simple custom function described in the full snippet below. And I've used the approach described in How to split a dataframe each time a string value changes in a column? to produce the necessary splits in the dataframe each time your averages cross eachother.

Plot

Complete code:

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:如何根据条件为两条线之间的填充着色?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆