|
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