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

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

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

我希望它通过的条件是:

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

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

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

【问题讨论】:

    标签: python charts plotly fill 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 根本不会绘制填充图。
    猜你喜欢
    • 2021-07-12
    • 1970-01-01
    • 1970-01-01
    • 2021-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-12
    • 2023-03-22
    相关资源
    最近更新 更多