6

使用 matplotlib,我们可以fill_between()像示例中那样“简单地”填充两条垂直线之间的区域:

https://matplotlib.org/3.2.1/gallery/lines_bars_and_markers/fill_between_demo.html#selectively-marking-horizo​​ntal-regions-across-the-whole-axes

使用 matplotlib,我可以制作我需要的东西:

在此处输入图像描述

我们有两个信号,我正在计算滚动/移动 Pearson 和 Spearman 的相关性。当相关性低于 -0.5 或高于 0.5 时,我想对周期进行着色(Pearson 为蓝色,Spearman 为橙色)。我还将所有情节中的周末都涂成灰色。

但是,我发现很难使用 Plotly 完成同样的任务。知道如何在两条水平线之间进行操作也将很有帮助。

请注意,我使用 Plotly 和 Dash 来加快几个绘图的可视化。用户要求更多“动态类型的东西”。但是,我不是 GUI 人,不能花时间在这上面,尽管我需要为他们提供初步结果。

顺便说一句,我过去尝试过 Bokeh,但由于某种我不记得的原因而放弃了。Plotly 看起来不错,因为我可以使用 Python 或 R,它们是我的主要开发工具。

谢谢,

卡洛斯

4

2 回答 2

6

我认为没有任何内置的 Plotly 方法相当于 matplotlib 的fill_between()方法。但是,您可以绘制形状,因此可能的解决方法是绘制一个灰色矩形并设置参数layer="below",以便信号仍然可见。您还可以将矩形的坐标设置在轴范围之外,以确保矩形延伸到绘图的边缘。

您可以通过绘制一个矩形并以类似方式设置轴范围来填充水平线之间的区域。

import numpy as np
import plotly.graph_objects as go

x = np.arange(0, 4 * np.pi, 0.01)
y = np.sin(x)

fig = go.Figure()
fig.add_trace(go.Scatter(
    x=x,
    y=y
))

# hard-code the axes
fig.update_xaxes(range=[0, 4 * np.pi])
fig.update_yaxes(range=[-1.2, 1.2])

# specify the corners of the rectangles
fig.update_layout(
    shapes=[
    dict(
        type="rect",
        xref="x",
        yref="y",
        x0="4",
        y0="-1.3",
        x1="5",
        y1="1.3",
        fillcolor="lightgray",
        opacity=0.4,
        line_width=0,
        layer="below"
    ),
    dict(
        type="rect",
        xref="x",
        yref="y",
        x0="9",
        y0="-1.3",
        x1="10",
        y1="1.3",
        fillcolor="lightgray",
        opacity=0.4,
        line_width=0,
        layer="below"
    ),
    ]
)

fig.show()

在此处输入图像描述

于 2020-08-19T21:35:01.190 回答
4

您尚未提供数据样本,因此我将使用综合时间序列向您展示如何使用自定义函数为多个不同类别添加具有定义的开始和停止日期的多个形状bgLevel


两条带有填充的垂直线很快就变成了一个矩形。矩形可以很容易地添加为形状,使用fig.add_shape. 下面的示例将向您展示如何查找特定标准给出的时段的开始日期和结束日期。在您的情况下,这些标准是变量的值是高于还是低于某个水平。

使用形状而不是迹线fig.add_trace()可以让您使用layer='below'. 并且形状轮廓可以很容易地使用隐藏 line=dict(color="rgba(0,0,0,0))

图 1:带有随机数据的时间序列图:

在此处输入图像描述

图 2:当 时,背景设置为不透明的灰色A > 100

在此处输入图像描述

图 2:背景也设置为不透明的红色D < 60

在此处输入图像描述

完整代码:

import numpy as np
import pandas as pd
import plotly.graph_objects as go
import plotly.express as px
import datetime

pd.set_option('display.max_rows', None)

# data sample
nperiods = 200
np.random.seed(123)
df = pd.DataFrame(np.random.randint(-10, 12, size=(nperiods, 4)),
                  columns=list('ABCD'))
datelist = pd.date_range(datetime.datetime(2020, 1, 1).strftime('%Y-%m-%d'),periods=nperiods).tolist()
df['dates'] = datelist 
df = df.set_index(['dates'])
df.index = pd.to_datetime(df.index)
df.iloc[0] = 0
df = df.cumsum().reset_index()

# function to set background color for a
# specified variable and a specified level



# plotly setup
fig = px.line(df, x='dates', y=df.columns[1:])
fig.update_xaxes(showgrid=True, gridwidth=1, gridcolor='rgba(0,0,255,0.1)')
fig.update_yaxes(showgrid=True, gridwidth=1, gridcolor='rgba(0,0,255,0.1)')

def bgLevels(fig, variable, level, mode, fillcolor, layer):
    """
    Set a specified color as background for given
    levels of a specified variable using a shape.
    
    Keyword arguments:
    ==================
    fig -- plotly figure
    variable -- column name in a pandas dataframe
    level -- int or float
    mode -- set threshold above or below
    fillcolor -- any color type that plotly can handle
    layer -- position of shape in plotly fiugre, like "below"
    
    """
    
    if mode == 'above':
        m = df[variable].gt(level)
    
    if mode == 'below':
        m = df[variable].lt(level)
        
    df1 = df[m].groupby((~m).cumsum())['dates'].agg(['first','last'])

    for index, row in df1.iterrows():
        #print(row['first'], row['last'])
        fig.add_shape(type="rect",
                        xref="x",
                        yref="paper",
                        x0=row['first'],
                        y0=0,
                        x1=row['last'],
                        y1=1,
                        line=dict(color="rgba(0,0,0,0)",width=3,),
                        fillcolor=fillcolor,
                        layer=layer) 
    return(fig)

fig = bgLevels(fig = fig, variable = 'A', level = 100, mode = 'above',
               fillcolor = 'rgba(100,100,100,0.2)', layer = 'below')

fig = bgLevels(fig = fig, variable = 'D', level = -60, mode = 'below',
               fillcolor = 'rgba(255,0,0,0.2)', layer = 'below')

fig.show()
于 2020-08-19T22:53:43.223 回答