Filling between two specific lines?

In a plot with several traces, i’m trying to fill the areas between two lines that i choose.
The desires effect, achieved with matplotlib.pyplot looks like this:

where the cyan and orange areas are filled between their respective trends, and up/down to the red line. The black line is unrelated to those filled areas, but should be plotted along with the blue line regardless.

Plotly has the following function:

plt.fill_between(x, y1, y2, color, alpha)

I tried achieving this with Plotly’s fill: 'tonexty', but this doesn’t work out well because of the black traces.

I’d love to hear of a solution / workaround for this.

Thanks!

HI @avimuni could you provide the data for this example you’re showing?

can also be easily reproduced with this example:

from matplotlib import pyplot as plt
import numpy as np
import pandas as pd

series1 = pd.Series(np.random.randn(100), index=pd.date_range('1/1/2000', periods=100))

series2 = series1 + np.random.randn(len(series1))

positive_contribution = series2 + 0.5
negative_contribution = series2 - 0.5

plt.plot(series1, color='black')
plt.plot(series2, color='red')
plt.fill_between(series2.index, series2, negative_contribution, color='cyan', alpha=0.2)
plt.fill_between(series2.index, series2, positive_contribution, color='orange', alpha=0.2)

Unfortunately not: name 'ts' is not defined

Found the answer elsewhere:

Apparently “tonexty” actually fill the space between the current trace and the trace that was previously added in the ‘trace storage’, and not to the ‘nearest’ trace. This means that the order in which the traces are added to the figure is the main factor in determining between which trends the fill happens.

A workaround can therefore be:

# add a transparent 'red' trace not visible on legend.
fig.add_trace(
    go.Scatter(
        x=series2.index,
        y=series2,
        fill=None,
        mode="lines",
        line_color="rgba(0,0,0,0)",
        showlegend=False,
    )
)
# add orange trace
fig.add_trace(
    go.Scatter(
        x=series2.index,
        y=positive_contribution,
        fill="tonexty",
        mode="lines",
        line_color="orange",
    )
)
# re add the red trace, but visible this time, as this is the last one
fig.add_trace(
    go.Scatter(
        x=series2.index,
        y=series2,
        fill=None,
        mode="lines",
        line_color="red",
    )
)
# add the cyan trace
fig.add_trace(
    go.Scatter(
        x=series2.index,
        y=negative_contribution,
        fill="tonexty",
        mode="lines",
        line_color="cyan",
    )
)
# finally add the black trace
fig.add_trace(
    go.Scatter(
        x=series1.index,
        y=series1,
        fill=None,
        mode="lines",
        line_color="black",
    )
)