From 7f10300bc36d4ac866e20d6e9075e6a83828c3b5 Mon Sep 17 00:00:00 2001 From: Vincent Cuenca Date: Wed, 16 Mar 2016 17:54:04 -0400 Subject: [PATCH 1/8] Add option to create vertically-oriented stem plots * Added docstrings for optional args in stem, made vertical default to false * Added flipping and renamed xs and ys in stem --- lib/matplotlib/axes/_axes.py | 34 +++++++++++++++++++++++++++------- lib/matplotlib/pyplot.py | 5 +++-- 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py index e5846422b9f9..45a43275e7fa 100644 --- a/lib/matplotlib/axes/_axes.py +++ b/lib/matplotlib/axes/_axes.py @@ -2723,7 +2723,7 @@ def broken_barh(self, xranges, yrange, **kwargs): @_preprocess_data() def stem(self, *args, linefmt=None, markerfmt=None, basefmt=None, bottom=0, - label=None, use_line_collection=True): + label=None, use_line_collection=True, vertical=False): """ Create a stem plot. @@ -2774,6 +2774,9 @@ def stem(self, *args, linefmt=None, markerfmt=None, basefmt=None, bottom=0, basefmt : str, default: 'C3-' ('C2-' in classic mode) A format string defining the properties of the baseline. + vertical : bool, optional (False) + If 'True', will produce a vertically-oriented stem plot. + bottom : float, default: 0 The y-position of the baseline. @@ -2862,9 +2865,16 @@ def stem(self, *args, linefmt=None, markerfmt=None, basefmt=None, bottom=0, else: basestyle, basemarker, basecolor = _process_plot_format(basefmt) + # Check if the user wants a vertical stem plot + if vertical: + x, y = y, x + # New behaviour in 3.1 is to use a LineCollection for the stemlines if use_line_collection: - stemlines = [((xi, bottom), (xi, yi)) for xi, yi in zip(x, y)] + if vertical: + stemlines = [((bottom, yi), (xi, yi)) for xi, yi in zip(x, y)] + else: + stemlines = [((xi, bottom), (xi, yi)) for xi, yi in zip(x, y)] if linestyle is None: linestyle = rcParams['lines.linestyle'] stemlines = mcoll.LineCollection(stemlines, linestyles=linestyle, @@ -2875,17 +2885,27 @@ def stem(self, *args, linefmt=None, markerfmt=None, basefmt=None, bottom=0, else: stemlines = [] for xi, yi in zip(x, y): - l, = self.plot([xi, xi], [bottom, yi], + if vertical: + xs = [bottom, xi] + ys = [yi, yi] + else: + xs = [xi, xi] + ys = [bottom, yi] + l, = self.plot(xs, ys, color=linecolor, linestyle=linestyle, marker=linemarker, label="_nolegend_") stemlines.append(l) markerline, = self.plot(x, y, color=markercolor, linestyle=markerstyle, marker=markermarker, label="_nolegend_") - - baseline, = self.plot([np.min(x), np.max(x)], [bottom, bottom], - color=basecolor, linestyle=basestyle, - marker=basemarker, label="_nolegend_") + if vertical: + baseline, = self.plot([bottom, bottom], [np.min(x), np.max(x)], + color=basecolor, linestyle=basestyle, + marker=basemarker, label="_nolegend_") + else: + baseline, = self.plot([np.min(x), np.max(x)], [bottom, bottom], + color=basecolor, linestyle=basestyle, + marker=basemarker, label="_nolegend_") stem_container = StemContainer((markerline, stemlines, baseline), label=label) diff --git a/lib/matplotlib/pyplot.py b/lib/matplotlib/pyplot.py index 70389be97e39..f97130dd4d38 100644 --- a/lib/matplotlib/pyplot.py +++ b/lib/matplotlib/pyplot.py @@ -3018,11 +3018,12 @@ def stackplot( @_copy_docstring_and_deprecators(Axes.stem) def stem( *args, linefmt=None, markerfmt=None, basefmt=None, bottom=0, - label=None, use_line_collection=True, data=None): + label=None, use_line_collection=True, vertical=False, + data=None): return gca().stem( *args, linefmt=linefmt, markerfmt=markerfmt, basefmt=basefmt, bottom=bottom, label=label, - use_line_collection=use_line_collection, + use_line_collection=use_line_collection, vertical=vertical, **({"data": data} if data is not None else {})) From a1ebd1f8adfd96880dce3195c8782220015b697a Mon Sep 17 00:00:00 2001 From: ItsRLuo Date: Thu, 17 Mar 2016 15:27:32 -0400 Subject: [PATCH 2/8] Changed orientation variable to string from boolean Also modified documentation for the change. Flipped thisx to thisy and vice versa when the orientation value is vertical --- lib/matplotlib/axes/_axes.py | 17 ++++++++++------- lib/matplotlib/pyplot.py | 7 ++++--- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py index 45a43275e7fa..4acba8c2d62a 100644 --- a/lib/matplotlib/axes/_axes.py +++ b/lib/matplotlib/axes/_axes.py @@ -2723,7 +2723,7 @@ def broken_barh(self, xranges, yrange, **kwargs): @_preprocess_data() def stem(self, *args, linefmt=None, markerfmt=None, basefmt=None, bottom=0, - label=None, use_line_collection=True, vertical=False): + label=None, use_line_collection=True, orientation='horizontal'): """ Create a stem plot. @@ -2774,8 +2774,9 @@ def stem(self, *args, linefmt=None, markerfmt=None, basefmt=None, bottom=0, basefmt : str, default: 'C3-' ('C2-' in classic mode) A format string defining the properties of the baseline. - vertical : bool, optional (False) - If 'True', will produce a vertically-oriented stem plot. + orientation : string, optional (horizontal) + If 'vertical', will produce a vertically-oriented stem plot, + else it will produce a horizontally-oriented stem plot. bottom : float, default: 0 The y-position of the baseline. @@ -2866,12 +2867,12 @@ def stem(self, *args, linefmt=None, markerfmt=None, basefmt=None, bottom=0, basestyle, basemarker, basecolor = _process_plot_format(basefmt) # Check if the user wants a vertical stem plot - if vertical: + if orientation == 'vertical': x, y = y, x # New behaviour in 3.1 is to use a LineCollection for the stemlines if use_line_collection: - if vertical: + if orientation == 'vertical': stemlines = [((bottom, yi), (xi, yi)) for xi, yi in zip(x, y)] else: stemlines = [((xi, bottom), (xi, yi)) for xi, yi in zip(x, y)] @@ -2885,7 +2886,7 @@ def stem(self, *args, linefmt=None, markerfmt=None, basefmt=None, bottom=0, else: stemlines = [] for xi, yi in zip(x, y): - if vertical: + if orientation == 'vertical': xs = [bottom, xi] ys = [yi, yi] else: @@ -2898,7 +2899,9 @@ def stem(self, *args, linefmt=None, markerfmt=None, basefmt=None, bottom=0, markerline, = self.plot(x, y, color=markercolor, linestyle=markerstyle, marker=markermarker, label="_nolegend_") - if vertical: + + if orientation == 'vertical': + x, y = y, x baseline, = self.plot([bottom, bottom], [np.min(x), np.max(x)], color=basecolor, linestyle=basestyle, marker=basemarker, label="_nolegend_") diff --git a/lib/matplotlib/pyplot.py b/lib/matplotlib/pyplot.py index f97130dd4d38..49df64fee1ed 100644 --- a/lib/matplotlib/pyplot.py +++ b/lib/matplotlib/pyplot.py @@ -3018,12 +3018,13 @@ def stackplot( @_copy_docstring_and_deprecators(Axes.stem) def stem( *args, linefmt=None, markerfmt=None, basefmt=None, bottom=0, - label=None, use_line_collection=True, vertical=False, - data=None): + label=None, use_line_collection=True, + orientation='horizontal', data=None): return gca().stem( *args, linefmt=linefmt, markerfmt=markerfmt, basefmt=basefmt, bottom=bottom, label=label, - use_line_collection=use_line_collection, vertical=vertical, + use_line_collection=use_line_collection, + orientation=orientation, **({"data": data} if data is not None else {})) From a1696cad8edf4bf30784e2fb0ba040617406fb97 Mon Sep 17 00:00:00 2001 From: Vincent Cuenca Date: Tue, 22 Mar 2016 13:30:18 -0400 Subject: [PATCH 3/8] Added whats_new entry for #5856 --- doc/users/next_whats_new/stem_orientation.rst | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 doc/users/next_whats_new/stem_orientation.rst diff --git a/doc/users/next_whats_new/stem_orientation.rst b/doc/users/next_whats_new/stem_orientation.rst new file mode 100644 index 000000000000..2565e6f6c25e --- /dev/null +++ b/doc/users/next_whats_new/stem_orientation.rst @@ -0,0 +1,11 @@ +Added *orientation* parameter for stem plots +-------------------------------------------- +When creating stem plots, you can now pass in an *orientation* argument to +`.Axes.stem` or `.pyplot.stem`. + +Currently, only ``'vertical'`` and ``'horizontal'`` orientations are supported, +with ``'horizontal'`` being the default. + +Example +``````` +stem(x, x, orientation='vertical') From fc6daff287623d8432cc62acd17240e4dd44387f Mon Sep 17 00:00:00 2001 From: Vincent Cuenca Date: Tue, 22 Mar 2016 18:47:13 -0400 Subject: [PATCH 4/8] Add stem orientation test and associated baseline images Co-authored-by: Elliott Sales de Andrade --- .../test_axes/stem_orientation.png | Bin 0 -> 14087 bytes lib/matplotlib/tests/test_axes.py | 13 +++++++++++++ 2 files changed, 13 insertions(+) create mode 100644 lib/matplotlib/tests/baseline_images/test_axes/stem_orientation.png diff --git a/lib/matplotlib/tests/baseline_images/test_axes/stem_orientation.png b/lib/matplotlib/tests/baseline_images/test_axes/stem_orientation.png new file mode 100644 index 0000000000000000000000000000000000000000..21614d9743111369ec5942098ec66a31204a5b53 GIT binary patch literal 14087 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 LOQGO0=HCAT7tE;T literal 0 HcmV?d00001 diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index 9b739aabc1ae..d62e06752f9e 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -3279,6 +3279,19 @@ def test_stem_dates(): ax.stem(xs, ys, "*-") +@pytest.mark.parametrize("use_line_collection", [True, False], + ids=['w/ line collection', 'w/o line collection']) +@image_comparison(['stem_orientation.png'], style='mpl20', remove_text=True) +def test_stem_orientation(use_line_collection): + x = np.linspace(0.1, 2*np.pi, 50) + args = (x, np.cos(x)) + kwargs = dict(linefmt='C2-.', markerfmt='kx', basefmt='C1-.', + use_line_collection=use_line_collection) + + fig, ax = plt.subplots() + ax.stem(*args, **kwargs, orientation='vertical') + + @image_comparison(['hist_stacked_stepfilled_alpha']) def test_hist_stacked_stepfilled_alpha(): # make some data From 77d8cfb898322e5eb840f172c088a16c6ef14c1e Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Wed, 5 Aug 2020 20:13:08 -0400 Subject: [PATCH 5/8] Add validation for the orientation in stem(). --- lib/matplotlib/axes/_axes.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py index 4acba8c2d62a..5c1f98d10c1e 100644 --- a/lib/matplotlib/axes/_axes.py +++ b/lib/matplotlib/axes/_axes.py @@ -2807,6 +2807,8 @@ def stem(self, *args, linefmt=None, markerfmt=None, basefmt=None, bottom=0, if not 1 <= len(args) <= 5: raise TypeError('stem expected between 1 and 5 positional ' 'arguments, got {}'.format(args)) + cbook._check_in_list(['horizontal', 'vertical'], + orientation=orientation) if len(args) == 1: y, = args From 54258c962415edb8043e21c6260d8e27a6d6cbd8 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Wed, 5 Aug 2020 21:13:22 -0400 Subject: [PATCH 6/8] Rename stem parameters to be clearer. They are no longer x/y when using a different orientation. Also, this should fix the unit conversion to use the correct Axis. --- lib/matplotlib/axes/_axes.py | 90 +++++++++++++++++++++--------------- 1 file changed, 53 insertions(+), 37 deletions(-) diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py index 5c1f98d10c1e..4e8bd0ce8189 100644 --- a/lib/matplotlib/axes/_axes.py +++ b/lib/matplotlib/axes/_axes.py @@ -2727,23 +2727,28 @@ def stem(self, *args, linefmt=None, markerfmt=None, basefmt=None, bottom=0, """ Create a stem plot. - A stem plot plots vertical lines at each *x* location from the baseline - to *y*, and places a marker there. + A stem plot draws lines perpendicular to a baseline at each location + *locs* from the baseline to *heads*, and places a marker there. For + horizontal stem plots (the default), the *locs* are *x* positions, and + the *heads* are *y* values. For vertical stem plots, the *locs* are + *y* positions, and the *heads* are *x* values. Call signature:: - stem([x,] y, linefmt=None, markerfmt=None, basefmt=None) + stem([locs,] heads, linefmt=None, markerfmt=None, basefmt=None) - The x-positions are optional. The formats may be provided either as - positional or as keyword-arguments. + The *locs*-positions are optional. The formats may be provided either + as positional or as keyword-arguments. Parameters ---------- - x : array-like, optional - The x-positions of the stems. Default: (0, 1, ..., len(y) - 1). + locs : array-like, default: (0, 1, ..., len(heads) - 1) + For horizontal stem plots, the x-positions of the stems. + For vertical stem plots, the y-positions of the stems. - y : array-like - The y-values of the stem heads. + heads : array-like + For horizontal stem plots, the y-values of the stem heads. + For vertical stem plots, the x-values of the stem heads. linefmt : str, optional A string defining the properties of the vertical lines. Usually, @@ -2774,7 +2779,7 @@ def stem(self, *args, linefmt=None, markerfmt=None, basefmt=None, bottom=0, basefmt : str, default: 'C3-' ('C2-' in classic mode) A format string defining the properties of the baseline. - orientation : string, optional (horizontal) + orientation : str, default: 'horizontal' If 'vertical', will produce a vertically-oriented stem plot, else it will produce a horizontally-oriented stem plot. @@ -2811,15 +2816,20 @@ def stem(self, *args, linefmt=None, markerfmt=None, basefmt=None, bottom=0, orientation=orientation) if len(args) == 1: - y, = args - x = np.arange(len(y)) + heads, = args + locs = np.arange(len(heads)) args = () else: - x, y, *args = args + locs, heads, *args = args - self._process_unit_info(xdata=x, ydata=y) - x = self.convert_xunits(x) - y = self.convert_yunits(y) + if orientation == 'horizontal': + self._process_unit_info(xdata=locs, ydata=heads) + locs = self.convert_xunits(locs) + heads = self.convert_yunits(heads) + else: + self._process_unit_info(xdata=heads, ydata=locs) + heads = self.convert_xunits(heads) + locs = self.convert_yunits(locs) # defaults for formats if linefmt is None: @@ -2868,16 +2878,16 @@ def stem(self, *args, linefmt=None, markerfmt=None, basefmt=None, bottom=0, else: basestyle, basemarker, basecolor = _process_plot_format(basefmt) - # Check if the user wants a vertical stem plot - if orientation == 'vertical': - x, y = y, x - # New behaviour in 3.1 is to use a LineCollection for the stemlines if use_line_collection: if orientation == 'vertical': - stemlines = [((bottom, yi), (xi, yi)) for xi, yi in zip(x, y)] + stemlines = [ + ((bottom, loc), (head, loc)) + for loc, head in zip(locs, heads)] else: - stemlines = [((xi, bottom), (xi, yi)) for xi, yi in zip(x, y)] + stemlines = [ + ((loc, bottom), (loc, head)) + for loc, head in zip(locs, heads)] if linestyle is None: linestyle = rcParams['lines.linestyle'] stemlines = mcoll.LineCollection(stemlines, linestyles=linestyle, @@ -2887,30 +2897,36 @@ def stem(self, *args, linefmt=None, markerfmt=None, basefmt=None, bottom=0, # Old behaviour is to plot each of the lines individually else: stemlines = [] - for xi, yi in zip(x, y): + for loc, head in zip(locs, heads): if orientation == 'vertical': - xs = [bottom, xi] - ys = [yi, yi] + xs = [bottom, head] + ys = [loc, loc] else: - xs = [xi, xi] - ys = [bottom, yi] + xs = [loc, loc] + ys = [bottom, head] l, = self.plot(xs, ys, color=linecolor, linestyle=linestyle, marker=linemarker, label="_nolegend_") stemlines.append(l) - markerline, = self.plot(x, y, color=markercolor, linestyle=markerstyle, - marker=markermarker, label="_nolegend_") - if orientation == 'vertical': - x, y = y, x - baseline, = self.plot([bottom, bottom], [np.min(x), np.max(x)], - color=basecolor, linestyle=basestyle, - marker=basemarker, label="_nolegend_") + marker_x = heads + marker_y = locs + baseline_x = [bottom, bottom] + baseline_y = [np.min(locs), np.max(locs)] else: - baseline, = self.plot([np.min(x), np.max(x)], [bottom, bottom], - color=basecolor, linestyle=basestyle, - marker=basemarker, label="_nolegend_") + marker_x = locs + marker_y = heads + baseline_x = [np.min(locs), np.max(locs)] + baseline_y = [bottom, bottom] + + markerline, = self.plot(marker_x, marker_y, + color=markercolor, linestyle=markerstyle, + marker=markermarker, label="_nolegend_") + + baseline, = self.plot(baseline_x, baseline_y, + color=basecolor, linestyle=basestyle, + marker=basemarker, label="_nolegend_") stem_container = StemContainer((markerline, stemlines, baseline), label=label) From c022b2261e4638500494039276ecc77d428c0e22 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Tue, 11 Aug 2020 00:56:42 -0400 Subject: [PATCH 7/8] Flip meaning of orientation in `stem()`. --- doc/users/next_whats_new/stem_orientation.rst | 4 +-- lib/matplotlib/axes/_axes.py | 30 +++++++++---------- lib/matplotlib/pyplot.py | 4 +-- lib/matplotlib/tests/test_axes.py | 2 +- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/doc/users/next_whats_new/stem_orientation.rst b/doc/users/next_whats_new/stem_orientation.rst index 2565e6f6c25e..0ee3edba7120 100644 --- a/doc/users/next_whats_new/stem_orientation.rst +++ b/doc/users/next_whats_new/stem_orientation.rst @@ -4,8 +4,8 @@ When creating stem plots, you can now pass in an *orientation* argument to `.Axes.stem` or `.pyplot.stem`. Currently, only ``'vertical'`` and ``'horizontal'`` orientations are supported, -with ``'horizontal'`` being the default. +with ``'vertical'`` being the default. Example ``````` -stem(x, x, orientation='vertical') +stem(x, x, orientation='horizontal') diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py index 4e8bd0ce8189..d0ecdcdca7a1 100644 --- a/lib/matplotlib/axes/_axes.py +++ b/lib/matplotlib/axes/_axes.py @@ -2723,14 +2723,14 @@ def broken_barh(self, xranges, yrange, **kwargs): @_preprocess_data() def stem(self, *args, linefmt=None, markerfmt=None, basefmt=None, bottom=0, - label=None, use_line_collection=True, orientation='horizontal'): + label=None, use_line_collection=True, orientation='vertical'): """ Create a stem plot. A stem plot draws lines perpendicular to a baseline at each location *locs* from the baseline to *heads*, and places a marker there. For - horizontal stem plots (the default), the *locs* are *x* positions, and - the *heads* are *y* values. For vertical stem plots, the *locs* are + vertical stem plots (the default), the *locs* are *x* positions, and + the *heads* are *y* values. For horizontal stem plots, the *locs* are *y* positions, and the *heads* are *x* values. Call signature:: @@ -2743,12 +2743,12 @@ def stem(self, *args, linefmt=None, markerfmt=None, basefmt=None, bottom=0, Parameters ---------- locs : array-like, default: (0, 1, ..., len(heads) - 1) - For horizontal stem plots, the x-positions of the stems. - For vertical stem plots, the y-positions of the stems. + For vertical stem plots, the x-positions of the stems. + For horizontal stem plots, the y-positions of the stems. heads : array-like - For horizontal stem plots, the y-values of the stem heads. - For vertical stem plots, the x-values of the stem heads. + For vertical stem plots, the y-values of the stem heads. + For horizontal stem plots, the x-values of the stem heads. linefmt : str, optional A string defining the properties of the vertical lines. Usually, @@ -2779,12 +2779,12 @@ def stem(self, *args, linefmt=None, markerfmt=None, basefmt=None, bottom=0, basefmt : str, default: 'C3-' ('C2-' in classic mode) A format string defining the properties of the baseline. - orientation : str, default: 'horizontal' - If 'vertical', will produce a vertically-oriented stem plot, - else it will produce a horizontally-oriented stem plot. + orientation : str, default: 'vertical' + If 'vertical', will produce a plot with stems oriented vertically, + otherwise the stems will be oriented horizontally. bottom : float, default: 0 - The y-position of the baseline. + The y/x-position of the baseline (depending on orientation). label : str, default: None The label to use for the stems in legends. @@ -2822,7 +2822,7 @@ def stem(self, *args, linefmt=None, markerfmt=None, basefmt=None, bottom=0, else: locs, heads, *args = args - if orientation == 'horizontal': + if orientation == 'vertical': self._process_unit_info(xdata=locs, ydata=heads) locs = self.convert_xunits(locs) heads = self.convert_yunits(heads) @@ -2880,7 +2880,7 @@ def stem(self, *args, linefmt=None, markerfmt=None, basefmt=None, bottom=0, # New behaviour in 3.1 is to use a LineCollection for the stemlines if use_line_collection: - if orientation == 'vertical': + if orientation == 'horizontal': stemlines = [ ((bottom, loc), (head, loc)) for loc, head in zip(locs, heads)] @@ -2898,7 +2898,7 @@ def stem(self, *args, linefmt=None, markerfmt=None, basefmt=None, bottom=0, else: stemlines = [] for loc, head in zip(locs, heads): - if orientation == 'vertical': + if orientation == 'horizontal': xs = [bottom, head] ys = [loc, loc] else: @@ -2909,7 +2909,7 @@ def stem(self, *args, linefmt=None, markerfmt=None, basefmt=None, bottom=0, marker=linemarker, label="_nolegend_") stemlines.append(l) - if orientation == 'vertical': + if orientation == 'horizontal': marker_x = heads marker_y = locs baseline_x = [bottom, bottom] diff --git a/lib/matplotlib/pyplot.py b/lib/matplotlib/pyplot.py index 49df64fee1ed..62076a4a6e36 100644 --- a/lib/matplotlib/pyplot.py +++ b/lib/matplotlib/pyplot.py @@ -3018,8 +3018,8 @@ def stackplot( @_copy_docstring_and_deprecators(Axes.stem) def stem( *args, linefmt=None, markerfmt=None, basefmt=None, bottom=0, - label=None, use_line_collection=True, - orientation='horizontal', data=None): + label=None, use_line_collection=True, orientation='vertical', + data=None): return gca().stem( *args, linefmt=linefmt, markerfmt=markerfmt, basefmt=basefmt, bottom=bottom, label=label, diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index d62e06752f9e..9048f5f5cf82 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -3289,7 +3289,7 @@ def test_stem_orientation(use_line_collection): use_line_collection=use_line_collection) fig, ax = plt.subplots() - ax.stem(*args, **kwargs, orientation='vertical') + ax.stem(*args, **kwargs, orientation='horizontal') @image_comparison(['hist_stacked_stepfilled_alpha']) From 13d962aeca9224e7ec41d4cd2291b3bcd2a20d90 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Wed, 12 Aug 2020 23:43:00 -0400 Subject: [PATCH 8/8] Improve stem orientation tests and what's new doc. --- doc/users/next_whats_new/stem_orientation.rst | 16 +++++++++------- lib/matplotlib/tests/test_axes.py | 18 ++++++++---------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/doc/users/next_whats_new/stem_orientation.rst b/doc/users/next_whats_new/stem_orientation.rst index 0ee3edba7120..727c9c6ec60f 100644 --- a/doc/users/next_whats_new/stem_orientation.rst +++ b/doc/users/next_whats_new/stem_orientation.rst @@ -1,11 +1,13 @@ Added *orientation* parameter for stem plots -------------------------------------------- -When creating stem plots, you can now pass in an *orientation* argument to -`.Axes.stem` or `.pyplot.stem`. -Currently, only ``'vertical'`` and ``'horizontal'`` orientations are supported, -with ``'vertical'`` being the default. +By default, stem lines are vertical. They can be changed to horizontal using +the *orientation* parameter of `.Axes.stem` or `.pyplot.stem`: -Example -``````` -stem(x, x, orientation='horizontal') +.. plot:: + + locs = np.linspace(0.1, 2 * np.pi, 25) + heads = np.cos(locs) + + fig, ax = plt.subplots() + ax.stem(locs, heads, orientation='horizontal') diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index 9048f5f5cf82..84b13405af33 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -3245,14 +3245,13 @@ def test_hist_stacked_weighted(): @image_comparison(['stem.png'], style='mpl20', remove_text=True) def test_stem(use_line_collection): x = np.linspace(0.1, 2 * np.pi, 100) - args = (x, np.cos(x)) - # Label is a single space to force a legend to be drawn, but to avoid any - # text being drawn - kwargs = dict(linefmt='C2-.', markerfmt='k+', basefmt='C1-.', - label=' ', use_line_collection=use_line_collection) fig, ax = plt.subplots() - ax.stem(*args, **kwargs) + # Label is a single space to force a legend to be drawn, but to avoid any + # text being drawn + ax.stem(x, np.cos(x), + linefmt='C2-.', markerfmt='k+', basefmt='C1-.', label=' ', + use_line_collection=use_line_collection) ax.legend() @@ -3284,12 +3283,11 @@ def test_stem_dates(): @image_comparison(['stem_orientation.png'], style='mpl20', remove_text=True) def test_stem_orientation(use_line_collection): x = np.linspace(0.1, 2*np.pi, 50) - args = (x, np.cos(x)) - kwargs = dict(linefmt='C2-.', markerfmt='kx', basefmt='C1-.', - use_line_collection=use_line_collection) fig, ax = plt.subplots() - ax.stem(*args, **kwargs, orientation='horizontal') + ax.stem(x, np.cos(x), + linefmt='C2-.', markerfmt='kx', basefmt='C1-.', + use_line_collection=use_line_collection, orientation='horizontal') @image_comparison(['hist_stacked_stepfilled_alpha'])