8000 Improve example for fill_between · matplotlib/matplotlib@a191e9d · GitHub
[go: up one dir, main page]

Skip to content

Commit a191e9d

Browse files
committed
Improve example for fill_between
1 parent efafb6c commit a191e9d

File tree

1 file changed

+111
-40
lines changed

1 file changed

+111
-40
lines changed

examples/lines_bars_and_markers/fill_between_demo.py

Lines changed: 111 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,27 @@
33
Filling the area between lines
44
==============================
55
6-
This example shows how to use ``fill_between`` to color between lines based on
7-
user-defined logic.
6+
This example shows how to use `~.axes.Axes.fill_between` to color the area
7+
between two lines.
88
"""
99

1010
import matplotlib.pyplot as plt
1111
import numpy as np
1212

13+
###############################################################################
14+
#
15+
# Basic usage
16+
# -----------
17+
# The parameters *y1* and *y2* can be a scalar, indicating a horizontal
18+
# boundary a the given y-values. If only *y1* is given, *y2* defaults to 0.
19+
1320
x = np.arange(0.0, 2, 0.01)
1421
y1 = np.sin(2 * np.pi * x)
1522
y2 = 1.2 * np.sin(4 * np.pi * x)
1623

17-
###############################################################################
18-
1924
fig, (ax1, ax2, ax3) = plt.subplots(3, 1, sharex=True)
2025

21-
ax1.fill_between(x, 0, y1)
26+
ax1.fill_between(x, y1)
2227
ax1.set_ylabel('between y1 and 0')
2328

2429
ax2.fill_between(x, y1, 1)
@@ -29,50 +34,116 @@
2934
ax3.set_xlabel('x')
3035

3136
###############################################################################
32-
# Now fill between y1 and y2 where a logical condition is met. Note
33-
# this is different than calling
34-
# ``fill_between(x[where], y1[where], y2[where] ...)``
35-
# because of edge effects over multiple contiguous regions.
36-
37-
fig, (ax, ax1) = plt.subplots(2, 1, sharex=True)
38-
ax.plot(x, y1, x, y2, color='black')
39-
ax.fill_between(x, y1, y2, where=y2 >= y1, facecolor='green', interpolate=True)
40-
ax.fill_between(x, y1, y2, where=y2 <= y1, facecolor='red', interpolate=True)
41-
ax.set_title('fill between where')
42-
43-
# Test support for masked arrays.
44-
y2 = np.ma.masked_greater(y2, 1.0)
45-
ax1.plot(x, y1, x, y2, color='black')
46-
ax1.fill_between(x, y1, y2, where=y2 >= y1,
47-
facecolor='green', interpolate=True)
48-
ax1.fill_between(x, y1, y2, where=y2 <= y1,
49-
facecolor='red', interpolate=True)
50-
ax1.set_title('Now regions with y2>1 are masked')
37+
#
38+
# Example: Confidence bands
39+
# -------------------------
40+
# A common application for `~.axes.Axes.fill_between` is the indication of
41+
# confidence bands.
42+
#
43+
# `~.axes.Axes.fill_between` uses the colors of the color cycle as the fill
44+
# color. These may be a bit strong when applied to fill areas. It is
45+
# therefore often a good practice to lighten the color by making the area
46+
# semi-transparent using *alpha*.
47+
48+
# sphinx_gallery_thumbnail_number = 2
49+
50+
N = 21
51+
x = np.linspace(0, 10, 11)
52+
y = [3.9, 4.4, 10.8, 10.3, 11.2, 13.1, 14.1, 9.9, 13.9, 15.1, 12.5]
53+
54+
# fit a linear curve an estimate it's y-values and their error.
55+
a, b = np.polyfit(x, y, deg=1)
56+
y_est = a * x + b
57+
y_err = x.std() * np.sqrt(1/len(x) +
58+
(x - x.mean())**2 / np.sum((x - x.mean())**2))
59+
60+
fig, ax = plt.subplots()
61+
ax.plot(x, y_est, '-')
62+
ax.fill_between(x, y_est - y_err, y_est + y_err, alpha=0.2)
63+
ax.plot(x, y, 'o', color='tab:brown')
64+
65+
###############################################################################
66+
#
67+
# Selectively filling horizontal regions
68+
# --------------------------------------
69+
# The parameter *where* allows to specify the x-ranges to fill. It's a boolean
70+
# array with the same size as *x*.
71+
#
72+
# Only x-ranges of contiguous *True* sequences are filled. As a result the
73+
# range between neighboring *True* and *False* values is never filled. This
74+
# often undesired when the data points should represent a contiguous quantity.
75+
# It is therefore recommended to set ``interpolate=True`` unless the
76+
# x-distance of the data points is fine enough so that the above effect is not
77+
# noticeable. Interpolation approximates the actual x position at which the
78+
# *where* condition will change and extends the filling up to there.
79+
80+
x = np.array([0, 1, 2, 3])
81+
y1 = np.array([1, 1, 0, 0])
82+
y2 = np.array([0, 0, 1, 1])
83+
84+
fig, (ax1, ax2) = plt.subplots(2, 1, sharex=True)
85+
86+
ax1.set_title('interpolation=False')
87+
ax1.plot(x, y1, 'o--')
88+
ax1.plot(x, y2, 'o--')
89+
ax1.fill_between(x, y1, y2, where=(y1 > y2), color='C0', alpha=0.3)
90+
ax1.fill_between(x, y1, y2, where=(y1 < y2), color='C1', alpha=0.3)
91+
92+
ax2.set_title('interpolation=True')
93+
ax2.plot(x, y1, 'o--')
94+
ax2.plot(x, y2, 'o--')
95+
ax2.fill_between(x, y1, y2, where=(y1 > y2), color='C0', alpha=0.3,
96+
interpolate=True)
97+
ax2.fill_between(x, y1, y2, where=(y1 <= y2), color='C1', alpha=0.3,
98+
interpolate=True)
5199

52100
###############################################################################
53-
# This example illustrates a problem; because of the data
54-
# gridding, there are undesired unfilled triangles at the crossover
55-
# points. A brute-force solution would be to interpolate all
56-
# arrays to a very fine grid before plotting.
101+
#
102+
# .. note::
103+
#
104+
# Similar gaps will occur if *y1* or *y2* are masked arrays. Since missing
105+
# values cannot be approximated, *interpolate* has no effect in this case.
106+
# The gaps around masked values can only be reduced by adding more data
107+
# points close to the masked values.
57108

58109

59110
###############################################################################
60-
# Use transforms to create axes spans where a certain condition is satisfied:
111+
#
112+
# Selectively marking horizontal regions across the whole Axes
113+
# ------------------------------------------------------------
114+
# The same selection mechanism can be applied to fill the full vertical height
115+
# of the axes. To be independent of y-limits, we add a transform that
116+
# interprets the x-values in data coorindates and the y-values in axes
117+
# coordinates.
118+
#
119+
# The following example marks the regions in which the y-data are above a
120+
# given threshold.
61121

62122
fig, ax = plt.subplots()
63-
y = np.sin(4 * np.pi * x)
123+
x = np.arange(0, 4 * np.pi, 0.01)
124+
y = np.sin(x)
64125
ax.plot(x, y, color='black')
65126

66-
# use data coordinates for the x-axis and the axes coordinates for the y-axis
67127
import matplotlib.transforms as mtransforms
68128
trans = mtransforms.blended_transform_factory(ax.transData, ax.transAxes)
69-
theta = 0.9
70-
ax.axhline(theta, color='green', lw=2, alpha=0.5)
71-
ax.axhline(-theta, color='red', lw=2, alpha=0.5)
72-
ax.fill_between(x, 0, 1, where=y > theta,
73-
facecolor='green', alpha=0.5, transform=trans)
74-
ax.fill_between(x, 0, 1, where=y < -theta,
75-
facecolor='red', alpha=0.5, transform=trans)
76-
77129

78-
plt.show()
130+
threshold = 0.75
131+
ax.axhline(threshold, color='green', lw=2, alpha=0.7)
132+
ax.fill_between(x, 0, 1, where=y > threshold,
133+
color='green', alpha=0.5, transform=trans)
134+
135+
136+
#############################################################################
137+
#
138+
# ------------
139+
#
140+
# References
141+
# """"""""""
142+
#
143+
# The use of the following functions, methods and classes is shown
144+
# in this example:
145+
146+
import matplotlib
147+
matplotlib.axes.Axes.fill_between
148+
matplotlib.pyplot.fill_between
149+
matplotlib.transforms.blended_transform_factory

0 commit comments

Comments
 (0)
0