|
3 | 3 | Filling the area between lines |
4 | 4 | ============================== |
5 | 5 |
|
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. |
8 | 8 | """ |
9 | 9 |
|
10 | 10 | import matplotlib.pyplot as plt |
11 | 11 | import numpy as np |
12 | 12 |
|
| 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 | + |
13 | 20 | x = np.arange(0.0, 2, 0.01) |
14 | 21 | y1 = np.sin(2 * np.pi * x) |
15 | | -y2 = 1.2 * np.sin(4 * np.pi * x) |
| 22 | +y2 = 0.8 * np.sin(4 * np.pi * x) |
16 | 23 |
|
17 | | -############################################################################### |
| 24 | +fig, (ax1, ax2, ax3) = plt.subplots(3, 1, sharex=True, figsize=(6, 6)) |
18 | 25 |
|
19 | | -fig, (ax1, ax2, ax3) = plt.subplots(3, 1, sharex=True) |
20 | | - |
21 | | -ax1.fill_between(x, 0, y1) |
22 | | -ax1.set_ylabel('between y1 and 0') |
| 26 | +ax1.fill_between(x, y1) |
| 27 | +ax1.set_title('fill between y1 and 0') |
23 | 28 |
|
24 | 29 | ax2.fill_between(x, y1, 1) |
25 | | -ax2.set_ylabel('between y1 and 1') |
| 30 | +ax2.set_title('fill between y1 and 1') |
26 | 31 |
|
27 | 32 | ax3.fill_between(x, y1, y2) |
28 | | -ax3.set_ylabel('between y1 and y2') |
| 33 | +ax3.set_title('fill between y1 and y2') |
29 | 34 | ax3.set_xlabel('x') |
| 35 | +fig.tight_layout() |
30 | 36 |
|
31 | 37 | ############################################################################### |
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') |
| 38 | +# |
| 39 | +# Example: Confidence bands |
| 40 | +# ------------------------- |
| 41 | +# A common application for `~.axes.Axes.fill_between` is the indication of |
| 42 | +# confidence bands. |
| 43 | +# |
| 44 | +# `~.axes.Axes.fill_between` uses the colors of the color cycle as the fill |
| 45 | +# color. These may be a bit strong when applied to fill areas. It is |
| 46 | +# therefore often a good practice to lighten the color by making the area |
| 47 | +# semi-transparent using *alpha*. |
| 48 | + |
| 49 | +# sphinx_gallery_thumbnail_number = 2 |
| 50 | + |
| 51 | +N = 21 |
| 52 | +x = np.linspace(0, 10, 11) |
| 53 | +y = [3.9, 4.4, 10.8, 10.3, 11.2, 13.1, 14.1, 9.9, 13.9, 15.1, 12.5] |
| 54 | + |
| 55 | +# fit a linear curve an estimate its y-values and their error. |
| 56 | +a, b = np.polyfit(x, y, deg=1) |
| 57 | +y_est = a * x + b |
| 58 | +y_err = x.std() * np.sqrt(1/len(x) + |
| 59 | + (x - x.mean())**2 / np.sum((x - x.mean())**2)) |
| 60 | + |
| 61 | +fig, ax = plt.subplots() |
| 62 | +ax.plot(x, y_est, '-') |
| 63 | +ax.fill_between(x, y_est - y_err, y_est + y_err, alpha=0.2) |
| 64 | +ax.plot(x, y, 'o', color='tab:brown') |
51 | 65 |
|
52 | 66 | ############################################################################### |
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. |
| 67 | +# |
| 68 | +# Selectively filling horizontal regions |
| 69 | +# -------------------------------------- |
| 70 | +# The parameter *where* allows to specify the x-ranges to fill. It's a boolean |
| 71 | +# array with the same size as *x*. |
| 72 | +# |
| 73 | +# Only x-ranges of contiguous *True* sequences are filled. As a result the |
| 74 | +# range between neighboring *True* and *False* values is never filled. This |
| 75 | +# often undesired when the data points should represent a contiguous quantity. |
| 76 | +# It is therefore recommended to set ``interpolate=True`` unless the |
| 77 | +# x-distance of the data points is fine enough so that the above effect is not |
| 78 | +# noticeable. Interpolation approximates the actual x position at which the |
| 79 | +# *where* condition will change and extends the filling up to there. |
| 80 | + |
| 81 | +x = np.array([0, 1, 2, 3]) |
| 82 | +y1 = np.array([0.8, 0.8, 0.2, 0.2]) |
| 83 | +y2 = np.array([0, 0, 1, 1]) |
| 84 | + |
| 85 | +fig, (ax1, ax2) = plt.subplots(2, 1, sharex=True) |
| 86 | + |
| 87 | +ax1.set_title('interpolation=False') |
| 88 | +ax1.plot(x, y1, 'o--') |
| 89 | +ax1.plot(x, y2, 'o--') |
| 90 | +ax1.fill_between(x, y1, y2, where=(y1 > y2), color='C0', alpha=0.3) |
| 91 | +ax1.fill_between(x, y1, y2, where=(y1 < y2), color='C1', alpha=0.3) |
| 92 | + |
| 93 | +ax2.set_title('interpolation=True') |
| 94 | +ax2.plot(x, y1, 'o--') |
| 95 | +ax2.plot(x, y2, 'o--') |
| 96 | +ax2.fill_between(x, y1, y2, where=(y1 > y2), color='C0', alpha=0.3, |
| 97 | + interpolate=True) |
| 98 | +ax2.fill_between(x, y1, y2, where=(y1 <= y2), color='C1', alpha=0.3, |
| 99 | + interpolate=True) |
| 100 | +fig.tight_layout() |
57 | 101 |
|
| 102 | +############################################################################### |
| 103 | +# |
| 104 | +# .. note:: |
| 105 | +# |
| 106 | +# Similar gaps will occur if *y1* or *y2* are masked arrays. Since missing |
| 107 | +# values cannot be approximated, *interpolate* has no effect in this case. |
| 108 | +# The gaps around masked values can only be reduced by adding more data |
| 109 | +# points close to the masked values. |
58 | 110 |
|
59 | 111 | ############################################################################### |
60 | | -# Use transforms to create axes spans where a certain condition is satisfied: |
| 112 | +# |
| 113 | +# Selectively marking horizontal regions across the whole Axes |
| 114 | +# ------------------------------------------------------------ |
| 115 | +# The same selection mechanism can be applied to fill the full vertical height |
| 116 | +# of the axes. To be independent of y-limits, we add a transform that |
| 117 | +# interprets the x-values in data coorindates and the y-values in axes |
| 118 | +# coordinates. |
| 119 | +# |
| 120 | +# The following example marks the regions in which the y-data are above a |
| 121 | +# given threshold. |
61 | 122 |
|
62 | 123 | fig, ax = plt.subplots() |
63 | | -y = np.sin(4 * np.pi * x) |
| 124 | +x = np.arange(0, 4 * np.pi, 0.01) |
| 125 | +y = np.sin(x) |
64 | 126 | ax.plot(x, y, color='black') |
65 | 127 |
|
66 | | -# use data coordinates for the x-axis and the axes coordinates for the y-axis |
67 | | -import matplotlib.transforms as mtransforms |
68 | | -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 | | - |
77 | | - |
78 | | -plt.show() |
| 128 | +threshold = 0.75 |
| 129 | +ax.axhline(threshold, color='green', lw=2, alpha=0.7) |
| 130 | +ax.fill_between(x, 0, 1, where=y > threshold, |
| 131 | + color='green', alpha=0.5, transform=ax.get_xaxis_transform()) |
| 132 | + |
| 133 | +############################################################################# |
| 134 | +# |
| 135 | +# ------------ |
| 136 | +# |
| 137 | +# References |
| 138 | +# """""""""" |
| 139 | +# |
| 140 | +# The use of the following functions, methods and classes is shown |
| 141 | +# in this example: |
| 142 | + |
| 143 | +import matplotlib |
| 144 | +matplotlib.axes.Axes.fill_between |
| 145 | +matplotlib.pyplot.fill_between |
| 146 | +matplotlib.axes.Axes.get_xaxis_transform |
0 commit comments