Python 如何用plotly制作阴影区或交替的背景色?

Python: How to make shaded areas or alternating background color using plotly?


问题

只用 plot.ly的这几行代码, 就可以在jupyter笔记本中得到下面的图:

片段1:

import plotly
import cufflinks as cf
from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot
init_notebook_mode(connected=True)

iplot(cf.datagen.lines().iplot(asFigure=True,
                               kind='scatter',xTitle='Dates',yTitle='Returns',title='Returns'))

Plot 1:

enter image description here

你如何设置,使你能像 这个帖子 中显示的那样,用 matplotlib 在下面的情节中交替使用背景颜色?

这里有一个链接 ,解释了如何像这样添加阴影区域:

插图2:

df.iplot(vspan={'x0':'2015-02-15','x1':'2015-03-15','color':'rgba(30,30,30,0.3)','fill':True,'opacity':.4}, 
         filename='cufflinks/custom-regions')

Plot 2:

enter image description here

谢谢你的任何建议!

这个 s Tackoverflow.com/q/29968152/4249707 答案可以帮助你。 cufflinks 你是用哪个上面的 plotly 不能做这样的改动
答案1

正如问题中所建议的,一个可能的解决方案是在 vspan 函数中。然而,使用 hspan 为Y轴添加多个阴影区域似乎比使用 vspan 和X轴要容易得多。后者需要多做一些调整。更多的细节可以在我建议的解决方案之后找到。


下面的图是由下面的片段和函数 multiShades 产生的。

绘图:

enter image description here

剪辑。

### Setup from the question ###

import plotly
import cufflinks as cf
from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot
import pandas as pd
import numpy as np
from IPython.display import HTML
from IPython.core.display import display, HTML
import copy

# setup
init_notebook_mode(connected=True)
np.random.seed(123)
cf.set_config_file(theme='pearl')

# Random data using cufflinks
df = cf.datagen.lines()

fig = df.iplot(asFigure=True, kind='scatter',
               xTitle='Dates',yTitle='Returns',title='Returns',
               vspan={'x0':'2015-01-11','x1':'2015-02-22','color':'rgba(30,30,30,0.3)','fill':True,'opacity':.4})

### ANSWER ###

xStart = ['2015-01-11', '2015-02-08', '2015-03-08', '2015-04-05']
xStop = ['2015-01-25', '2015-02-22', '2015-03-22', '2015-04-10']

def multiShades(plot, x0, x1):
    """ Adds shaded areas for specified dates in a plotly plot.
        The lines of the areas are set to transparent using rgba(0,0,0,0)
    """
    # get start and end dates
    x0 = xStart
    x1 = xStop

    # get dict from tuple made by vspan()
    xElem = fig['layout']['shapes'][0]

    # container (list) for dicts / shapes
    shp_lst=[]

    # make dicts according to x0 and X1
    # and edit elements of those dicts
    for i in range(0,len(x0)):
        shp_lst.append(copy.deepcopy(xElem))
        shp_lst[i]['x0'] = x0[i]
        shp_lst[i]['x1'] = x1[i]
        shp_lst[i]['line']['color'] = 'rgba(0,0,0,0)'

    # replace shape in fig with multiple new shapes
    fig['layout']['shapes']= tuple(shp_lst)
    return(fig)

fig = multiShades(plot=fig, x0=xStart, x1=xStop)

iplot(fig)

一些细节。

函数 vspan 为元组 fig['layout']['shapes'] "填充 "了一个字典,其形式为:

{'fillcolor': 'rgba(187, 187, 187, 0.4)',
 'line': {'color': '#BBBBBB', 'dash': 'solid', 'width': 1},
 'type': 'rect',
 'x0': '2015-01-11',
 'x1': '2015-02-22',
 'xref': 'x',
 'y0': 0,
 'y1': 1,
 'yref': 'paper'}

我的函数只是取了那个字典,做了一些副本,根据函数参数编辑这些副本,然后用函数中的一个新元组替换原来的元组。

挑战:

当增加更多的形状时,这种方法可能会变得有点棘手。此外,日期必须是硬编码的--至少在有人找到答案之前, 如何检索主要刻度线和网格线的值?

答案2

你现在可以用 fig.add_vrect() 在plotly 4.12中添加的方法来做这个。 例如,要添加对应于白天的阴影区域,需要有一个列表,早上,指定每天的早上时间,然后:

for morning in mornings:
    fig.add_vrect(
        x0=morning,
        x1=morning + timedelta(hours=12),
        fillcolor="white",
        opacity=0.1,
        line_width=0,
    )