Home > database >  How to fill lower part of the plot until specified range
How to fill lower part of the plot until specified range

Time:11-22

Assume I have the following data:

x = np.array([0, 100, 300, 500, 700, 900, 1100, 1300, 1500, 1700, 1900])
y = pd.DataFrame([1.000000, 0.966757, 0.853819, 0.693619, 0.564981, 0.470379, 0.372452, 0.275968, 0.195698, 0.125962, 0.071663],
                 index=(0, 100, 300, 500, 700, 900, 1100, 1300, 1500, 1700, 1900))

mean = 0.5
sigma_1 = 0.34
range = 0.17

yy = np.array(y)
yyy = yy[:, 0]

I need to use fill_between to fill the lower part of my plot until the specific value (here is identified as range), and although I have used the interpolate=True it will give me the following plot.

Any help is highly appreciated.

fig, ax = plt.subplots()
ax.plot(y)
ax.set_ylim(ymin=0)
plt.axhline(y=range, color='gray', linestyle='--', xmax=0.84)
plt.axhline(y=mean, color='gray', linestyle='--', xmax=0.42)
plt.axvline(x=np.interp(range, yyy[::-1], x[::-1]), ymin=0., ymax=.2, color='k', linewidth=1, lw='.8', linestyle='--')
plt.text(1500, .042, "range", fontsize=12, rotation=90)
plt.text(300, .55, 'mean', fontsize=12)
plt.text(300, .2, '1 STD', fontsize=12)
ax.fill_between(x, yyy, where=yyy >= range, interpolate=True, facecolor='red', edgecolor='0.2', alpha=.4)
plt.show()

enter image description here

CodePudding user response:

The interpolate= option of fill_between only does a limited adjustment. A better-looking result can be obtained by strongly increasing the number of points of the curve (via np.interp()).

Here is the updated code. Some other adjustments are:

  • Changing the variable name range to y_range to avoid shadowing the built-in range command
  • Not mixing the plt with the object-oriented interface
  • Changing axhline to hlines and calculate exact intersection points.
import matplotlib.pyplot as plt
import numpy as np

x = np.array([0, 100, 300, 500, 700, 900, 1100, 1300, 1500, 1700, 1900])
yy = np.array([1, 0.966757, 0.853819, 0.693619, 0.564981, 0.470379, 0.372452, 0.275968, 0.195698, 0.125962, 0.071663])

y_mean = 0.5
sigma_1 = 0.34
y_range = 0.17

fig, ax = plt.subplots()
ax.plot(x, yy)
ax.set_ylim(ymin=0)
ax.margins(x=0)  # no white space left and right
x_range = np.interp(y_range, yy[::-1], x[::-1])
ax.hlines(y=y_range, xmin=0, xmax=x_range, color='gray', linestyle='--')
x_mean = np.interp(y_mean, yy[::-1], x[::-1])
ax.hlines(y=y_mean, xmin=0, xmax=x_mean, color='gray', linestyle='--')
ax.vlines(x=x_range, ymin=0., ymax=y_range, color='k', linewidth=1, linestyle='--')
ax.text(x_range, y_range / 2, 'range\n', fontsize=12, rotation=90, ha='center', va='center')
ax.text(300, y_mean, 'mean\n', fontsize=12, va='center')
ax.text(300, y_range, '1 STD\n', fontsize=12, va='center')
x_long = np.linspace(x[0], x[-1], 500)
y_long = np.interp(x_long, x, yy)
ax.fill_between(x_long, y_long, where=y_long >= y_range, interpolate=True, facecolor='red', edgecolor='0.2', alpha=.4)
plt.show()

fill_between with more detailed curve

  • Related