Plotly: Bagaimana cara mengatur warna isian antara dua garis vertikal?
Menggunakan matplotlib, kita dapat "secara sepele" mengisi area antara dua garis vertikal menggunakan fill_between()
seperti pada contoh:
https://matplotlib.org/3.2.1/gallery/lines_bars_and_markers/fill_between_demo.html#selectively-marking-horizontal-regions-across-the-whole-axes
Dengan matplotlib, saya dapat membuat apa yang saya butuhkan:

Kami memiliki dua sinyal, dan saya menghitung korelasi Pearson dan Spearman yang berputar / bergerak. Ketika korelasinya berada di bawah -0,5 atau di atas 0,5, saya ingin memberi bayangan pada periode (biru untuk Pearson dan oranye untuk Spearman). Saya juga menggelapkan akhir pekan dengan warna abu-abu di semua plot.
Namun, saya kesulitan untuk mencapai hal yang sama menggunakan Plotly. Dan akan sangat membantu untuk mengetahui bagaimana melakukannya di antara dua garis horizontal.
Perhatikan bahwa saya menggunakan Plotly dan Dash untuk mempercepat visualisasi beberapa plot. Pengguna meminta "jenis hal yang lebih dinamis". Namun, saya bukan orang GUI dan tidak dapat menghabiskan waktu untuk ini, meskipun saya perlu memberi mereka makan dengan hasil awal.
BTW, saya mencoba Bokeh di masa lalu, dan saya menyerah untuk beberapa alasan yang tidak dapat saya ingat. Secara plot terlihat bagus karena saya dapat menggunakan baik dari Python atau R, yang merupakan alat pengembangan utama saya.
Terima kasih,
Carlos
Jawaban
Saya tidak berpikir ada metode Plotly built-in yang setara dengan fill_between()
metode matplotlib . Namun, Anda dapat menggambar bentuk sehingga kemungkinan solusinya adalah dengan menggambar persegi panjang abu-abu dan mengatur parameter layer="below"
sehingga sinyal tetap terlihat. Anda juga dapat menyetel koordinat persegi panjang di luar rentang sumbu Anda untuk memastikan persegi panjang tersebut meluas ke tepi plot.
Anda dapat mengisi area di antara garis horizontal dengan menggambar persegi panjang dan mengatur rentang sumbu dengan cara yang sama.
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()

Anda belum memberikan sampel data, jadi saya akan menggunakan rangkaian waktu sintetis untuk menunjukkan kepada Anda bagaimana Anda dapat menambahkan sejumlah bentuk dengan tanggal mulai dan berhenti yang ditentukan untuk beberapa kategori berbeda menggunakan fungsi kustom. bgLevel
Dua garis vertikal dengan isian di antara keduanya dengan sangat cepat berubah menjadi persegi panjang. Dan persegi panjang dapat dengan mudah ditambahkan sebagai bentuk menggunakan fig.add_shape
. Contoh di bawah ini akan menunjukkan kepada Anda bagaimana menemukan tanggal mulai dan berhenti untuk periode yang diberikan oleh kriteria tertentu. Dalam kasus Anda, kriteria ini adalah apakah nilai variabel lebih tinggi atau lebih rendah dari tingkat tertentu.
Menggunakan bentuk alih-alih jejak dengan fig.add_trace()
akan memungkinkan Anda menentukan posisi berkaitan dengan lapisan plot yang digunakan layer='below'
. Dan garis bentuk dapat dengan mudah disembunyikan menggunakan line=dict(color="rgba(0,0,0,0))
.
Plot 1: Gambar deret waktu dengan data acak:

Plot 2: Latar belakang disetel ke abu-abu buram jika A > 100
:

Plot 2: Latar belakang juga disetel ke merah buram saatD < 60

Kode lengkap:
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()