Home > Net >  Fill between two horizontal lines thresholds in matplotlib
Fill between two horizontal lines thresholds in matplotlib

Time:10-29

Dears, I need to make a fill between two thresholds in my chart I have tried with my code but it does not display, could you please tell me what I am doing wrong?

fig = plt.figure(figsize=(15, 6))
ax = fig.add_subplot(111)

ax = lacebita['Prob'].plot(figsize=(15, 7), )
xtime = np.linspace(1990,2021,384)


ax.plot(xtime, lacebita['Prob'], 'black', alpha=1.00, linewidth=2, label = 'Deciles')
ax.fill_between(xtime, 0., lacebita['Prob'], lacebita['Prob']< 30., color='red',  alpha=.75)
ax.axhline(50, linestyle='--', color='black',label='Percentile 50')
ax.axhline(33, linestyle='--', color='orange', label='Percentile 33')

ax.set_xlim(1990, 2021)
ax.set_ylim(0, 100, 10)

plt.grid(True)
plt.legend(loc = "upper left")
#ax.autoscale_view()

ax.set_title('Deciles para 12-Meses La Cebita(1990-2020)', fontsize=16)
ax.set_xlim(lacebita.index.min(), lacebita.index.max())

plt.savefig('deciles_12_lacebita.jpg')

enter image description here

CodePudding user response:

There are a couple of ways to go about it. One approach is to fill the space in between the two horizontal threshold lines:

# Make a fake function
t = 20
fs = 10
samples = np.linspace(0, t, int(fs*t), endpoint=False)
wave_y = np.sin(samples)
time_x = np.arange(0, len(wave_y))

# Set upper and lower thresholds where horizontal lines will go and fill in between
upper_th = 0.5
lower_th = -0.5

# Plot function
fig, ax = plt.subplots()
ax.plot(time_x, wave_y)
ax.grid()
ax.set_ylim([-1.25, 1.25])
ax.set_ylabel('y label')
ax.set_xlim([0, 125])
ax.set_xlabel('x label')

# Fill in area under the curve and the horizontal lines
ax.fill_between(x=time_x, y1=upper_th, y2=lower_th, color='red',  interpolate=True, alpha=.75)

# Horizontal lines
ax.axhline(upper_th, linestyle='--', color='black', label="upper_th: 0.5")
ax.axhline(lower_th, linestyle='--', color='orange', label='lower_th: - 0.5')
ax.legend()
plt.show()

fill figure

Or if you change y1 or y2, for example to y1=0, you can play around with where exactly the fill is.

enter image description here

Another method is to fill in between the curve and the horizontal dashed lines. To do that you could modify the original data so that the values that go above the upper threshold and below the lower threshold become the threshold values. In other words, we want to make a new y curve that includes the threshold points by eliminating the points that go above/below the threshold so that matplotlib understands that the horizontal lines are part of the y curve.

# Copy original data, we are now going to modify
new_wave_y = np.copy(wave_y)
# Change values outside thresholds to threshold value for fill in
new_wave_y[new_wave_y < lower_th] = lower_th
new_wave_y[new_wave_y > upper_th] = upper_th

This way we can use where in fill between to point out where exactly under the curve, including under/above the horizontal lines, matplotlib needs to fill in the area. The full script:

# Make a fake function
t = 20
fs = 10
samples = np.linspace(0, t, int(fs*t), endpoint=False)
wave_y = np.sin(samples)
time_x = np.arange(0, len(wave_y))

# Set upper and lower thresholds where horizontal lines will go and fill in between
upper_th = 0.5
lower_th = -0.5

# Copy original data, we are now going to modify
new_wave_y = np.copy(wave_y)
# Change values outside thresholds to threshold value for fill in
new_wave_y[new_wave_y < lower_th] = lower_th
new_wave_y[new_wave_y > upper_th] = upper_th

# Plot function
fig, ax = plt.subplots()
ax.plot(time_x, wave_y)
ax.grid()
ax.set_ylim([-1.25, 1.25])
ax.set_ylabel('y label')
ax.set_xlim([0, 125])
ax.set_xlabel('x label')

# Fill in area under the curve and the horizontal lines
ax.fill_between(x=time_x, y1=new_wave_y, where=(lower_th < new_wave_y), color='red',  interpolate=True, alpha=.75)
ax.fill_between(x=time_x, y1=new_wave_y, where=(new_wave_y < upper_th), color='red',  interpolate=True, alpha=.75)

# Horizontal lines
ax.axhline(upper_th, linestyle='--', color='black', label="upper_th: 0.5")
ax.axhline(lower_th, linestyle='--', color='orange', label='lower_th: - 0.5')
ax.legend()
plt.show()

fill_area

You can get some more information in the Matplotlib fill between demo and the fill between docs.

  • Related