From 0522695b98c12b70cc07c2811647457fa5341b86 Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Tue, 22 Sep 2020 15:55:52 +0200 Subject: [PATCH 1/2] StepPatch and stairs() docstring improvements. --- lib/matplotlib/axes/_axes.py | 11 +++++++---- lib/matplotlib/patches.py | 12 +++++++++--- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py index 30b2b6a4dfb4..07da78200315 100644 --- a/lib/matplotlib/axes/_axes.py +++ b/lib/matplotlib/axes/_axes.py @@ -6744,24 +6744,27 @@ def hist(self, x, bins=None, range=None, density=False, weights=None, def stairs(self, values, edges=None, *, orientation='vertical', baseline=0, fill=False, **kwargs): """ - A histogram-like line or filled plot. + A stepwise constant line or filled plot. Parameters ---------- values : array-like - An array of y-values. + The step heights. - edges : array-like, default: ``range(len(vals)+1)`` - A array of x-values, with ``len(edges) == len(vals) + 1``, + edges : array-like + The edge positions, with ``len(edges) == len(vals) + 1``, between which the curve takes on vals values. orientation : {'vertical', 'horizontal'}, default: 'vertical' + The direction of the steps. Vertical means that *values* are along + the y-axis, and edges are along the x-axis. baseline : float or None, default: 0 Determines starting value of the bounding edges or when ``fill=True``, position of lower edge. fill : bool, default: False + Whether the area under the step curve should be filled. Returns ------- diff --git a/lib/matplotlib/patches.py b/lib/matplotlib/patches.py index a616e3d77281..5caa3c7af009 100644 --- a/lib/matplotlib/patches.py +++ b/lib/matplotlib/patches.py @@ -990,7 +990,11 @@ def set_path(self, path): class StepPatch(PathPatch): - """An unclosed step path patch.""" + """ + A path patch describing a stepwise constant function. + + The path is unclosed. It starts and stops at baseline. + """ @docstring.dedent_interpd def __init__(self, values, edges, *, @@ -999,13 +1003,15 @@ def __init__(self, values, edges, *, Parameters ---------- values : array-like - An array of y-values. + The step heights. edges : array-like - A array of x-value edges, with ``len(edges) == len(vals) + 1``, + The edge positions, with ``len(edges) == len(vals) + 1``, between which the curve takes on vals values. orientation : {'vertical', 'horizontal'}, default: 'vertical' + The direction of the steps. Vertical means that *values* are along + the y-axis, and edges are along the x-axis. baseline : float or None, default: 0 Determines starting value of the bounding edges or when From 4590f16b7cbeddd4959548f82b5c5ecd7071345f Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Tue, 22 Sep 2020 16:31:04 +0200 Subject: [PATCH 2/2] Relate step() to stairs() --- .../next_whats_new/steppatch_and_stairs.rst | 14 ++++--- .../lines_bars_and_markers/stairs_demo.py | 37 +++++++++++-------- examples/lines_bars_and_markers/step_demo.py | 5 +++ lib/matplotlib/axes/_axes.py | 9 +++++ 4 files changed, 44 insertions(+), 21 deletions(-) diff --git a/doc/users/next_whats_new/steppatch_and_stairs.rst b/doc/users/next_whats_new/steppatch_and_stairs.rst index 268130ff9d1e..f5d76c5fd99b 100644 --- a/doc/users/next_whats_new/steppatch_and_stairs.rst +++ b/doc/users/next_whats_new/steppatch_and_stairs.rst @@ -1,7 +1,11 @@ New StepPatch artist and a stairs method ---------------------------------------- -New `~.matplotlib.patches.StepPatch` artist and `.pyplot.stairs` method. -For both the artist and the function, the x-like edges input is one +`.pyplot.stairs` and the underlying artist `~.matplotlib.patches.StepPatch` +provide a cleaner interface for plotting stepwise constant functions for the +common case that you know the step edges. This superseeds many use cases of +`.pyplot.step`, for instance when plotting the output of `numpy.histogram`. + +For both the artist and the function, the x-like edges input is one element longer than the y-like values input .. plot:: @@ -10,12 +14,12 @@ longer than the y-like values input import matplotlib.pyplot as plt np.random.seed(0) - h, bins = np.histogram(np.random.normal(5, 2, 5000), - bins=np.linspace(0,10,20)) + h, edges = np.histogram(np.random.normal(5, 2, 5000), + bins=np.linspace(0,10,20)) fig, ax = plt.subplots(constrained_layout=True) - ax.stairs(h, bins) + ax.stairs(h, edges) plt.show() diff --git a/examples/lines_bars_and_markers/stairs_demo.py b/examples/lines_bars_and_markers/stairs_demo.py index d9f8cce98326..8667ddefa42b 100644 --- a/examples/lines_bars_and_markers/stairs_demo.py +++ b/examples/lines_bars_and_markers/stairs_demo.py @@ -3,13 +3,10 @@ Stairs Demo =========== -This example demonstrates the use of `~.matplotlib.pyplot.stairs` -for histogram and histogram-like data visualization and an associated -underlying `.StepPatch` artist, which is a specialized version of -`.PathPatch` specified by its bins and edges. +This example demonstrates the use of `~.matplotlib.pyplot.stairs` for stepwise +constant functions. A common use case is histogram and histogram-like data +visualization. -The primary difference to `~.matplotlib.pyplot.step` is that ``stairs`` -x-like edges input is one longer than its y-like values input. """ import numpy as np @@ -17,13 +14,13 @@ from matplotlib.patches import StepPatch np.random.seed(0) -h, bins = np.histogram(np.random.normal(5, 3, 5000), - bins=np.linspace(0, 10, 20)) +h, edges = np.histogram(np.random.normal(5, 3, 5000), + bins=np.linspace(0, 10, 20)) fig, axs = plt.subplots(3, 1, figsize=(7, 15)) -axs[0].stairs(h, bins, label='Simple histogram') -axs[0].stairs(h, bins+5, baseline=50, label='Modified baseline') -axs[0].stairs(h, bins+10, baseline=None, label='No edges') +axs[0].stairs(h, edges, label='Simple histogram') +axs[0].stairs(h, edges + 5, baseline=50, label='Modified baseline') +axs[0].stairs(h, edges + 10, baseline=None, label='No edges') axs[0].set_title("Step Histograms") axs[1].stairs(np.arange(1, 6, 1), fill=True, @@ -47,22 +44,30 @@ plt.show() ############################################################################# -# Comparison of `.pyplot.step` and `.pyplot.stairs`. +# Comparison of `.pyplot.step` and `.pyplot.stairs` +# ------------------------------------------------- +# +# `.pyplot.step` defines the positions of the steps as single values. The steps +# extend left/right/both ways from these reference values depending on the +# parameter *where*. The number of *x* and *y* values is the same. +# +# In contrast, `.pyplot.stairs` defines the positions of the steps via their +# bounds *edges*, which is one element longer than the step values. bins = np.arange(14) -centers = bins[:-1] + np.diff(bins)/2 +centers = bins[:-1] + np.diff(bins) / 2 y = np.sin(centers / 2) -plt.step(bins[:-1], y, where='post', label='Step(where="post")') +plt.step(bins[:-1], y, where='post', label='step(where="post")') plt.plot(bins[:-1], y, 'o--', color='grey', alpha=0.3) -plt.stairs(y - 1, bins, baseline=None, label='Stairs') +plt.stairs(y - 1, bins, baseline=None, label='stairs()') plt.plot(centers, y - 1, 'o--', color='grey', alpha=0.3) plt.plot(np.repeat(bins, 2), np.hstack([y[0], np.repeat(y, 2), y[-1]]) - 1, 'o', color='red', alpha=0.2) plt.legend() -plt.title('plt.step vs plt.stairs') +plt.title('step() vs. stairs()') plt.show() ############################################################################# diff --git a/examples/lines_bars_and_markers/step_demo.py b/examples/lines_bars_and_markers/step_demo.py index 46b370eefd4d..c079ef05daad 100644 --- a/examples/lines_bars_and_markers/step_demo.py +++ b/examples/lines_bars_and_markers/step_demo.py @@ -7,6 +7,11 @@ curves. In particular, it illustrates the effect of the parameter *where* on the step position. +.. note:: + + For the common case that you know the edge positions, use `.pyplot.stairs` + instead. + The circular markers created with `.pyplot.plot` show the actual data positions so that it's easier to see the effect of *where*. diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py index 07da78200315..f13980bfc28a 100644 --- a/lib/matplotlib/axes/_axes.py +++ b/lib/matplotlib/axes/_axes.py @@ -2036,6 +2036,15 @@ def step(self, x, y, *args, where='pre', data=None, **kwargs): formatting options. Most of the concepts and parameters of plot can be used here as well. + .. note:: + + This method uses a standard plot with a step drawstyle: The *x* + values are the reference positions and steps extend left/right/both + directions depending on *where*. + + For the common case where you know the values and edges of the + steps, use `~.Axes.stairs` instead. + Parameters ---------- x : array-like