当线越过某个限制时用不同颜色填充区域 Plotly

Filling area with different colors when line cross some limit Plotly

尝试创建在 1.01 和 1.00 上有两条线穿过图表的图表,我想在线高于 1.01 时将颜色更改为绿色,当线在 1.01 和 1.01 之间时更改为黄色,低于 1.00 时更改颜色变红。

chartData = {'Price': [0.965879, 0.964773, 0.96447, 0.961223, 0.958788, 0.956747, 0.958788, 0.959872, 0.959868, 0.960104, 0.961375, 0.962256, 0.963297, 0.963315, 0.964611, 0.964513, 0.963761, 0.963763, 0.963922, 0.963907, 0.963857, 0.963265, 0.963293, 0.963171, 0.96318, 0.963707, 0.964389, 0.964352, 0.963077, 0.961785, 0.959572, 0.958703, 0.959223, 0.95819, 0.952994, 0.95124, 0.950693, 0.950906, 0.95184, 0.951838, 1.053997, 1.060501, 1.060672, 1.060486, 1.060171, 1.060241, 1.059292, 1.059263, 1.059205, 0.95906, 0.954787, 0.954901, 0.954993, 0.955447, 0.955465, 0.955626, 0.953638, 0.952751, 0.951972, 0.950729, 0.950532, 0.952849, 0.952773, 0.952682, 0.952351, 0.948383, 0.94847, 0.948451, 0.95198, 0.952234, 0.951982, 0.952163, 0.952301, 0.952407, 0.955843, 0.956628, 0.957734, 0.957548, 0.95771, 0.956813, 0.958674, 0.958295, 0.954697, 0.953861, 0.955926, 0.953264, 0.951443, 0.950245, 0.949453, 0.949492, 0.948764, 0.946932, 0.949487, 0.950302, 0.950381, 0.949979, 0.948601, 0.949252, 0.949217, 0.949271, 0.947859, 0.947683, 0.947763, 0.947593, 0.948247, 0.9483, 0.948568, 0.947236, 0.946515, 0.946128, 0.946793, 0.946244, 0.951683, 0.951324, 0.950662, 0.949001, 0.947648, 0.946191, 0.946928, 0.933038, 0.92239, 0.923197, 0.925719, 0.937193, 0.93354, 0.932933, 0.932073, 0.931954, 0.932393, 0.931602, 0.932908, 0.932966, 0.933866, 0.931223, 0.929834, 0.933195, 0.936534, 0.935959, 0.932762, 0.931187, 0.937434, 0.937664, 0.936378, 0.934742, 0.934742], 'Date': [1652117700000, 1652118000000, 1652118300000, 1652118600000, 1652118900000, 1652119200000, 1652119500000, 1652119800000, 1652120100000, 1652120400000, 1652120700000, 1652121000000, 1652121300000, 1652121600000, 1652121900000, 1652122200000, 1652122500000, 1652122800000, 1652123100000, 1652123400000, 1652123700000, 1652124000000, 1652124300000, 1652124600000, 1652124900000, 1652125200000, 1652125500000, 1652125800000, 1652126100000, 1652126400000, 1652126700000, 1652127000000, 1652127300000, 1652127600000, 1652127900000, 1652128200000, 1652128500000, 1652128800000, 1652129100000, 1652129400000, 1652129700000, 1652130000000, 1652130300000, 1652130600000, 1652130900000, 1652131200000, 1652131500000, 1652131800000, 1652132100000, 1652132400000, 1652132700000, 1652133000000, 1652133300000, 1652133600000, 1652133900000, 1652134200000, 1652134500000, 1652134800000, 1652135100000, 1652135400000, 1652135700000, 1652136000000, 1652136300000, 1652136600000, 1652136900000, 1652137200000, 1652137500000, 1652137800000, 1652138100000, 1652138400000, 1652138700000, 1652139000000, 1652139300000, 1652139600000, 1652139900000, 1652140200000, 1652140500000, 1652140800000, 1652141100000, 1652141400000, 1652141700000, 1652142000000, 1652142300000, 1652142600000, 1652142900000, 1652143200000, 1652143500000, 1652143800000, 1652144100000, 1652144400000, 1652144700000, 1652145000000, 1652145300000, 1652145600000, 1652145900000, 1652146200000, 1652146500000, 1652146800000, 1652147100000, 1652147400000, 1652147700000, 1652148000000, 1652148300000, 1652148600000, 1652148900000, 1652149200000, 1652149500000, 1652149800000, 1652150100000, 1652150400000, 1652150700000, 1652151000000, 1652151300000, 1652151600000, 1652151900000, 1652152200000, 1652152500000, 1652152800000, 1652153100000, 1652153400000, 1652153700000, 1652154000000, 1652154300000, 1652154600000, 1652154900000, 1652155200000, 1652155500000, 1652155800000, 1652156100000, 1652156400000, 1652156700000, 1652157000000, 1652157300000, 1652157600000, 1652157900000, 1652158200000, 1652158500000, 1652158800000, 1652159100000, 1652159400000, 1652159700000, 1652160000000, 1652160300000, 1652160600000, 1652160636000]}

df: DataFrame = pd.DataFrame.from_dict(chatData).fillna(method="backfill")
df['Date'] = pd.to_datetime(df['Date'], unit='ms')

fig = px.area(df, x='Date', y="Price")
fig.show()

实现这一点的一种可能方法是修改您的线以在您的线与限制 y-values 相交的地方插入新点,然后使用 np.nan 应用蒙版,如下所示:

import plotly.graph_objects as go
import numpy as np

def modify_coords(x, y, y_lim):
    """If a line segment defined by `(x1, y1) -> (x2, y2)` intercepts
    a limiting y-value, divide this segment by inserting a new point
    such that y_newpoint = y_lim.
    """
    xv, yv = [x[0]], [y[0]]
    for i in range(len(x) - 1):
        xc, xn = x[i:i+2]
        yc, yn = y[i:i+2]
        if ((yc < y_lim) and (yn > y_lim)) or ((yc > y_lim) and (yn < y_lim)):
            xv.append(((y_lim - yc) / ((yn - yc) / (xn - xc))) + xc)
            yv.append(y_lim)
        xv.append(xn)
        yv.append(yn)
    return np.array(xv), np.array(yv)

x = np.linspace(-10, 10, 200)
y = 0.025 * np.cos(x) + 1
limits = [1, 1.01]

x_mod = x.copy()
y_mod = y.copy()
for l in limits:
    x_mod, y_mod = modify_coords(x_mod, y_mod, l)

y1, y2, y3 = [y_mod.copy() for i in range(3)]
y1[y1 < limits[1]] = np.nan
y2[(y2 < limits[0]) | (y2 >limits[1])] = np.nan
y3[y3 > limits[0]] = np.nan

fig = go.Figure([
    go.Scatter(x=x, y=limits[1]*np.ones_like(x), opacity=0, line_width=0, showlegend=False),
    go.Scatter(x=x_mod, y=y1, fill="tonexty", opacity=0.5),
    go.Scatter(x=x, y=limits[0]*np.ones_like(x), opacity=0, line_width=0, showlegend=False),
    go.Scatter(x=x_mod, y=y2, fill="tonexty", opacity=0.5),
    go.Scatter(x=x, y=limits[0]*np.ones_like(x), opacity=0, line_width=0, showlegend=False),
    go.Scatter(x=x_mod, y=y3, fill="tonexty", opacity=0.5),
])
fig