Matplotlib - Change line color above / below hline
I have a line graph and 2 hlines, all with different colors, and I fill in the areas where the main line intersects the hlines with the hline color. In addition to this, I would like to use the same color for the main line in these areas. In a nutshell, the current output is:
And the relevant code I'm currently using:
lower, upper = 20, 80
self.indicatorPlot.axhline(lower, color="red")
self.indicatorPlot.axhline(upper, color="green")
self.indicatorPlot.plot(self.chartTimes, self.indicatorData, color="blue")
self.indicatorPlot.fill_between(self.chartTimes, self.indicatorData, lower, where=(self.indicatorData <= lower), facecolor="red", interpolate=True)
self.indicatorPlot.fill_between(self.chartTimes, self.indicatorData, upper, where=(self.indicatorData >= upper), facecolor="green", interpolate=True)
source to share
Basically you can split your plot into three parts, values above upper
, values below lower
and values in the middle. In this sense, this question has already been asked and answered, for example.
- Python: is it possible to change the color of a line in a plot if it exceeds a certain range?
- Subject: color is more than different color
These solutions work fine if the point density is high enough so that the lines end up close enough to the threshold line.
In the event that you have large gaps, they probably don't fit well. So I am giving here a solution that interpolates the gaps so that the lines end exactly at the threshold line.
import numpy as np; np.random.seed(43)
import matplotlib.pyplot as plt
t = np.linspace(0,100,301)
x = np.cumsum(np.random.randn(len(t)))
lower,upper = 0,8
fig, ax=plt.subplots()
ax.axhline(lower, color="crimson")
ax.axhline(upper, color="limegreen")
def insertzeros(t, x, zero=0):
ta = []
positive = (x-zero) > 0
ti = np.where(np.bitwise_xor(positive[1:], positive[:-1]))[0]
for i in ti:
y_ = np.sort(x[i:i+2])
z_ = t[i:i+2][np.argsort(x[i:i+2])]
t_ = np.interp(zero, y_, z_)
ta.append( t_ )
tnew = np.append( t, np.array(ta) )
xnew = np.append( x, np.ones(len(ta))*zero )
xnew = xnew[tnew.argsort()]
tnew = np.sort(tnew)
return tnew, xnew
t1,x1 = insertzeros(t,x, zero=lower)
t1,x1 = insertzeros(t1,x1, zero=upper)
xm = np.copy(x1)
xm[(x1 < lower) | (x1 > upper)] = np.nan
ax.plot(t1,xm, color="C0")
xl = np.copy(x1)
xl[(x1 > lower)] = np.nan
ax.plot(t1,xl, color="crimson")
#
xu = np.copy(x1)
xu[(xu < upper)] = np.nan
ax.plot(t1,xu, color="limegreen")
ax.fill_between(t, x, lower, where=(x <= lower), facecolor="crimson", interpolate=True, alpha=0.5)
ax.fill_between(t, x, upper, where=(x >= upper), facecolor="limegreen", interpolate=True, alpha=0.5)
plt.show()
source to share