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()
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
toy_range
to avoid shadowing the built-inrange
command - Not mixing the
plt
with the object-oriented interface - Changing
axhline
tohlines
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()