From 18a3bee734302411dd7d19c0e08b1f2dc2bdc185 Mon Sep 17 00:00:00 2001 From: yozhikoff Date: Fri, 10 Jan 2020 17:39:46 +0300 Subject: [PATCH 01/22] Add multiple labels support to Axes.plot() --- lib/matplotlib/axes/_base.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index c6309b5ab9df..42218f6a0a22 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -1,4 +1,5 @@ from collections import OrderedDict +from collections.abc import Iterable from contextlib import ExitStack import functools import inspect @@ -446,8 +447,22 @@ def _plot_args(self, tup, kwargs, return_kwargs=False): ncx, ncy = x.shape[1], y.shape[1] if ncx > 1 and ncy > 1 and ncx != ncy: raise ValueError(f"x has {ncx} columns but y has {ncy} columns") + + if ('label' in kwargs and isinstance(kwargs['label'], Iterable) + and not isinstance(kwargs['label'], str)): + if len(kwargs['label']) != max(ncx, ncy): + raise ValueError(f"if label is iterable label and input data" + f" must have same length, but have lengths " + f"{len(kwargs['label'])} and " + f"{max(ncx, ncy)}") + + result = (func(x[:, j % ncx], y[:, j % ncy], kw, + {**kwargs, 'label':kwargs['label'][j]}) + for j in range(max(ncx, ncy))) + result = (func(x[:, j % ncx], y[:, j % ncy], kw, kwargs) - for j in range(max(ncx, ncy))) + for j in range(max(ncx, ncy))) + if return_kwargs: return list(result) else: From b99c8ac3dfa96f2b82cb0616ca73d9eedee79d92 Mon Sep 17 00:00:00 2001 From: yozhikoff Date: Fri, 10 Jan 2020 18:57:10 +0300 Subject: [PATCH 02/22] Add multiple label support for Axes.plot() --- lib/matplotlib/axes/_base.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index 42218f6a0a22..ba0b553a0906 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -448,8 +448,9 @@ def _plot_args(self, tup, kwargs, return_kwargs=False): if ncx > 1 and ncy > 1 and ncx != ncy: raise ValueError(f"x has {ncx} columns but y has {ncy} columns") - if ('label' in kwargs and isinstance(kwargs['label'], Iterable) - and not isinstance(kwargs['label'], str)): + if ('label' in kwargs and max(ncx, ncy) > 1 + and isinstance(kwargs['label'], Iterable) + and not isinstance(kwargs['label'], str)): if len(kwargs['label']) != max(ncx, ncy): raise ValueError(f"if label is iterable label and input data" f" must have same length, but have lengths " From 4efe548cabd4ca02dba8233ba658bb2276c42659 Mon Sep 17 00:00:00 2001 From: yozhikoff Date: Fri, 10 Jan 2020 21:42:52 +0300 Subject: [PATCH 03/22] Add tests for multiple label --- lib/matplotlib/tests/test_legend.py | 69 +++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/lib/matplotlib/tests/test_legend.py b/lib/matplotlib/tests/test_legend.py index cd0cd8be85ca..11f006dc6f93 100644 --- a/lib/matplotlib/tests/test_legend.py +++ b/lib/matplotlib/tests/test_legend.py @@ -671,3 +671,72 @@ def test_no_warn_big_data_when_loc_specified(): ax.plot(np.arange(5000), label=idx) legend = ax.legend('best') fig.draw_artist(legend) # Check that no warning is emitted. + + +def test_plot_multiple_input_multiple_label(): + # test ax.plot() with multidimensional input + # and multiple labels + x = [1, 2, 5] + y = [[2, 4, 3], [4, 7, 1], [3, 9, 2]] + + label_arrays = [['one', 'two', 'three'], + ('one', 'two', 'three'), + np.array(['one', 'two', 'three'])] + + for label in label_arrays: + fig, ax = plt.subplots() + ax.plot(x, y, label=label) + leg = ax.legend() + + assert len(leg.get_texts()) == 3 + assert leg.get_texts()[0].get_text() == 'one' + assert leg.get_texts()[1].get_text() == 'two' + assert leg.get_texts()[2].get_text() == 'three' + + +def test_plot_multiple_input_single_label(): + # test ax.plot() with multidimensional input + # and single label + x = [1, 2, 5] + y = [[2, 4, 3], [4, 7, 1], [3, 9, 2]] + labels = ['one', 1, int] + + for label in labels: + fig, ax = plt.subplots() + ax.plot(x, y, label=label) + leg = ax.legend() + + assert len(leg.get_texts()) == 3 + assert leg.get_texts()[0].get_text() == str(label) + assert leg.get_texts()[1].get_text() == str(label) + assert leg.get_texts()[2].get_text() == str(label) + + +def test_plot_single_input_multiple_label(): + # test ax.plot() with 1D array like input + # and iterable label + x = [1, 2, 5] + y = [2, 4, 3] + + label_arrays = [['one', 'two', 'three'], + ('one', 'two', 'three'), + np.array(['one', 'two', 'three'])] + + for label in label_arrays: + fig, ax = plt.subplots() + ax.plot(x, y, label=label) + leg = ax.legend() + + assert len(leg.get_texts()) == 1 + assert leg.get_texts()[0].get_text() == str(label) + + +def test_plot_multiple_label_incorrect_length_exception(): + # check that exception is raised for + # iterable label with incorrect length + with pytest.raises(Exception): + x = [1, 2, 5] + y = [[2, 4, 3], [4, 7, 1], [3, 9, 2]] + label = ['one', 'two'] + fig, ax = plt.subplots() + ax.plot(x, y, label=label) \ No newline at end of file From 2b7189e865b35377c48ffa502269a94fd531ee8b Mon Sep 17 00:00:00 2001 From: yozhikoff Date: Sat, 11 Jan 2020 01:38:02 +0300 Subject: [PATCH 04/22] Fix pep8 errors --- lib/matplotlib/tests/test_legend.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/matplotlib/tests/test_legend.py b/lib/matplotlib/tests/test_legend.py index 11f006dc6f93..ad8032cf21dd 100644 --- a/lib/matplotlib/tests/test_legend.py +++ b/lib/matplotlib/tests/test_legend.py @@ -680,8 +680,8 @@ def test_plot_multiple_input_multiple_label(): y = [[2, 4, 3], [4, 7, 1], [3, 9, 2]] label_arrays = [['one', 'two', 'three'], - ('one', 'two', 'three'), - np.array(['one', 'two', 'three'])] + ('one', 'two', 'three'), + np.array(['one', 'two', 'three'])] for label in label_arrays: fig, ax = plt.subplots() @@ -719,8 +719,8 @@ def test_plot_single_input_multiple_label(): y = [2, 4, 3] label_arrays = [['one', 'two', 'three'], - ('one', 'two', 'three'), - np.array(['one', 'two', 'three'])] + ('one', 'two', 'three'), + np.array(['one', 'two', 'three'])] for label in label_arrays: fig, ax = plt.subplots() @@ -739,4 +739,4 @@ def test_plot_multiple_label_incorrect_length_exception(): y = [[2, 4, 3], [4, 7, 1], [3, 9, 2]] label = ['one', 'two'] fig, ax = plt.subplots() - ax.plot(x, y, label=label) \ No newline at end of file + ax.plot(x, y, label=label) From ee36d9598e8029e57dbf3dbc86e7942a57a24394 Mon Sep 17 00:00:00 2001 From: yozhikoff Date: Wed, 29 Jan 2020 18:45:35 +0300 Subject: [PATCH 05/22] Make test more precise --- lib/matplotlib/tests/test_legend.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/matplotlib/tests/test_legend.py b/lib/matplotlib/tests/test_legend.py index ad8032cf21dd..4c9bfd4bb54c 100644 --- a/lib/matplotlib/tests/test_legend.py +++ b/lib/matplotlib/tests/test_legend.py @@ -732,9 +732,9 @@ def test_plot_single_input_multiple_label(): def test_plot_multiple_label_incorrect_length_exception(): - # check that exception is raised for - # iterable label with incorrect length - with pytest.raises(Exception): + # check that excepton is raised if multiple labels + # are given, but number of on labels != number of lines + with pytest.raises(ValueError): x = [1, 2, 5] y = [[2, 4, 3], [4, 7, 1], [3, 9, 2]] label = ['one', 'two'] From 8b8202ce137ab933b6068556cfcd31fc1951f536 Mon Sep 17 00:00:00 2001 From: yozhikoff Date: Sun, 17 May 2020 03:20:19 +0300 Subject: [PATCH 06/22] Remove second return --- lib/matplotlib/axes/_base.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index ba0b553a0906..8dbbf338a5ca 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -456,12 +456,13 @@ def _plot_args(self, tup, kwargs, return_kwargs=False): f" must have same length, but have lengths " f"{len(kwargs['label'])} and " f"{max(ncx, ncy)}") + elif 'label' in kwargs: + kwargs['label'] = [kwargs['label']] * max(ncx, ncy) + else: + kwargs['label'] = [None] * max(ncx, ncy) - result = (func(x[:, j % ncx], y[:, j % ncy], kw, - {**kwargs, 'label':kwargs['label'][j]}) - for j in range(max(ncx, ncy))) - - result = (func(x[:, j % ncx], y[:, j % ncy], kw, kwargs) + result = (func(x[:, j % ncx], y[:, j % ncy], kw, + {**kwargs, 'label': kwargs['label'][j]}) for j in range(max(ncx, ncy))) if return_kwargs: From e9b3d97058b489c2ed7182878d0f385a84b5a054 Mon Sep 17 00:00:00 2001 From: yozhikoff Date: Sat, 4 Jul 2020 23:52:13 +0300 Subject: [PATCH 07/22] Rebase PR --- lib/matplotlib/axes/_base.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index 8dbbf338a5ca..12fb472236da 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -449,8 +449,8 @@ def _plot_args(self, tup, kwargs, return_kwargs=False): raise ValueError(f"x has {ncx} columns but y has {ncy} columns") if ('label' in kwargs and max(ncx, ncy) > 1 - and isinstance(kwargs['label'], Iterable) - and not isinstance(kwargs['label'], str)): + and isinstance(kwargs['label'], Iterable) + and not isinstance(kwargs['label'], str)): if len(kwargs['label']) != max(ncx, ncy): raise ValueError(f"if label is iterable label and input data" f" must have same length, but have lengths " From 7f786746538d8bb5c51dc23f900d929f9ad204df Mon Sep 17 00:00:00 2001 From: yozhikoff Date: Sun, 5 Jul 2020 13:38:51 +0300 Subject: [PATCH 08/22] Add whats_new entry --- .../multiple_labels_for_Axes_plot.rst | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 doc/users/next_whats_new/multiple_labels_for_Axes_plot.rst diff --git a/doc/users/next_whats_new/multiple_labels_for_Axes_plot.rst b/doc/users/next_whats_new/multiple_labels_for_Axes_plot.rst new file mode 100644 index 000000000000..4b8de04a9fb6 --- /dev/null +++ b/doc/users/next_whats_new/multiple_labels_for_Axes_plot.rst @@ -0,0 +1,20 @@ +An iterable object with labels can be passed to `Axes.plot()` +------------------------------------------------------------- + +If multidimensional data is used for plotting, labels can be specified in +a vectorized way with an iterable object of size corresponding to the +data array shape (exactly 5 labels are expected when plotting 5 lines). +It works with `Axes.plot()` as well as with it's wrapper `plt.plot()`. + +.. plot:: + + from matplotlib import pyplot as plt + + x = [1, 2, 5] + + y = [[2, 4, 3], + [4, 7, 1], + [3, 9, 2]] + + plt.plot(x, y, label=['one', 'two', 'three']) + plt.legend() \ No newline at end of file From 353985a9ecdd923c5d57da7cd61f0aec75b5ee93 Mon Sep 17 00:00:00 2001 From: yozhikoff Date: Sun, 5 Jul 2020 15:50:42 +0300 Subject: [PATCH 09/22] Fix reST formatting --- doc/users/next_whats_new/multiple_labels_for_Axes_plot.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/users/next_whats_new/multiple_labels_for_Axes_plot.rst b/doc/users/next_whats_new/multiple_labels_for_Axes_plot.rst index 4b8de04a9fb6..4260fcb93d10 100644 --- a/doc/users/next_whats_new/multiple_labels_for_Axes_plot.rst +++ b/doc/users/next_whats_new/multiple_labels_for_Axes_plot.rst @@ -1,10 +1,10 @@ -An iterable object with labels can be passed to `Axes.plot()` +An iterable object with labels can be passed to `.Axes.plot` ------------------------------------------------------------- If multidimensional data is used for plotting, labels can be specified in a vectorized way with an iterable object of size corresponding to the data array shape (exactly 5 labels are expected when plotting 5 lines). -It works with `Axes.plot()` as well as with it's wrapper `plt.plot()`. +It works with `.Axes.plot` as well as with it's wrapper `.pyplot.plot`. .. plot:: From 7fac6d3c304f86c4b53f627b062039b5bf3387e8 Mon Sep 17 00:00:00 2001 From: yozhikoff <35387375+yozhikoff@users.noreply.github.com> Date: Fri, 10 Jul 2020 02:44:48 +0300 Subject: [PATCH 10/22] Apply suggestions from code review Co-authored-by: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> --- .../multiple_labels_for_Axes_plot.rst | 21 +++++++--------- lib/matplotlib/axes/_base.py | 24 +++++++++---------- lib/matplotlib/tests/test_legend.py | 12 ++++------ 3 files changed, 24 insertions(+), 33 deletions(-) diff --git a/doc/users/next_whats_new/multiple_labels_for_Axes_plot.rst b/doc/users/next_whats_new/multiple_labels_for_Axes_plot.rst index 4260fcb93d10..1a87da7d17e4 100644 --- a/doc/users/next_whats_new/multiple_labels_for_Axes_plot.rst +++ b/doc/users/next_whats_new/multiple_labels_for_Axes_plot.rst @@ -1,20 +1,17 @@ An iterable object with labels can be passed to `.Axes.plot` ------------------------------------------------------------- -If multidimensional data is used for plotting, labels can be specified in -a vectorized way with an iterable object of size corresponding to the -data array shape (exactly 5 labels are expected when plotting 5 lines). -It works with `.Axes.plot` as well as with it's wrapper `.pyplot.plot`. +When plotting multiple datasets by passing 2D data as *y* value to `~.Axes.plot`, labels for the datasets can be passed as a list, the length matching the number of columns in *y*. .. plot:: - from matplotlib import pyplot as plt + import matplotlib.pyplot as plt + + x = [1, 2, 3] - x = [1, 2, 5] + y = [[1, 9], + [2, 8], + [4, 6]] - y = [[2, 4, 3], - [4, 7, 1], - [3, 9, 2]] - - plt.plot(x, y, label=['one', 'two', 'three']) - plt.legend() \ No newline at end of file + plt.plot(x, y, label=['low', 'high']) + plt.legend() diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index 12fb472236da..fe56dad187c4 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -448,22 +448,20 @@ def _plot_args(self, tup, kwargs, return_kwargs=False): if ncx > 1 and ncy > 1 and ncx != ncy: raise ValueError(f"x has {ncx} columns but y has {ncy} columns") - if ('label' in kwargs and max(ncx, ncy) > 1 - and isinstance(kwargs['label'], Iterable) - and not isinstance(kwargs['label'], str)): - if len(kwargs['label']) != max(ncx, ncy): - raise ValueError(f"if label is iterable label and input data" - f" must have same length, but have lengths " - f"{len(kwargs['label'])} and " - f"{max(ncx, ncy)}") - elif 'label' in kwargs: - kwargs['label'] = [kwargs['label']] * max(ncx, ncy) + label = kwargs.get('label') + n_datasets = max(ncx, ncy) + if n_datasets > 1 and not cbook.is_scalar_or_string(label): + if len(label) != n_datasets: + raise ValueError(f"label must be scalar or have the same " + f"length as the input data, but found " + f"{len(label)} for {n_datasets} datasets.") + labels = label else: - kwargs['label'] = [None] * max(ncx, ncy) + labels = [label] * n_datasets result = (func(x[:, j % ncx], y[:, j % ncy], kw, - {**kwargs, 'label': kwargs['label'][j]}) - for j in range(max(ncx, ncy))) + {**kwargs, 'label': label}) + for j, label in enumerate(labels)) if return_kwargs: return list(result) diff --git a/lib/matplotlib/tests/test_legend.py b/lib/matplotlib/tests/test_legend.py index 4c9bfd4bb54c..db965d4e299a 100644 --- a/lib/matplotlib/tests/test_legend.py +++ b/lib/matplotlib/tests/test_legend.py @@ -688,10 +688,8 @@ def test_plot_multiple_input_multiple_label(): ax.plot(x, y, label=label) leg = ax.legend() - assert len(leg.get_texts()) == 3 - assert leg.get_texts()[0].get_text() == 'one' - assert leg.get_texts()[1].get_text() == 'two' - assert leg.get_texts()[2].get_text() == 'three' + legend_texts = [entry.get_text() for entry in leg.get_texts()] + assert legend_texts == ['one', 'two', 'three'] def test_plot_multiple_input_single_label(): @@ -706,10 +704,8 @@ def test_plot_multiple_input_single_label(): ax.plot(x, y, label=label) leg = ax.legend() - assert len(leg.get_texts()) == 3 - assert leg.get_texts()[0].get_text() == str(label) - assert leg.get_texts()[1].get_text() == str(label) - assert leg.get_texts()[2].get_text() == str(label) + legend_texts = [entry.get_text() for entry in leg.get_texts()] + assert legend_texts == [str(label)] * 3 def test_plot_single_input_multiple_label(): From dee18de01d0afed4aff843235d776eebc21330ec Mon Sep 17 00:00:00 2001 From: yozhikoff Date: Fri, 10 Jul 2020 03:36:02 +0300 Subject: [PATCH 11/22] Make tests more readable --- .../multiple_labels_for_Axes_plot.rst | 6 +-- lib/matplotlib/tests/test_legend.py | 48 +++++++++---------- 2 files changed, 26 insertions(+), 28 deletions(-) diff --git a/doc/users/next_whats_new/multiple_labels_for_Axes_plot.rst b/doc/users/next_whats_new/multiple_labels_for_Axes_plot.rst index 1a87da7d17e4..70dab44a22ec 100644 --- a/doc/users/next_whats_new/multiple_labels_for_Axes_plot.rst +++ b/doc/users/next_whats_new/multiple_labels_for_Axes_plot.rst @@ -9,9 +9,9 @@ When plotting multiple datasets by passing 2D data as *y* value to `~.Axes.plot` x = [1, 2, 3] - y = [[1, 9], - [2, 8], - [4, 6]] + y = [[1, 2], + [2, 5], + [4, 9]] plt.plot(x, y, label=['low', 'high']) plt.legend() diff --git a/lib/matplotlib/tests/test_legend.py b/lib/matplotlib/tests/test_legend.py index db965d4e299a..57c8b67e2b09 100644 --- a/lib/matplotlib/tests/test_legend.py +++ b/lib/matplotlib/tests/test_legend.py @@ -676,53 +676,49 @@ def test_no_warn_big_data_when_loc_specified(): def test_plot_multiple_input_multiple_label(): # test ax.plot() with multidimensional input # and multiple labels - x = [1, 2, 5] - y = [[2, 4, 3], [4, 7, 1], [3, 9, 2]] - - label_arrays = [['one', 'two', 'three'], - ('one', 'two', 'three'), - np.array(['one', 'two', 'three'])] - + x = [1, 2, 3] + y = [[1, 2], + [2, 5], + [4, 9]] + label_arrays = [['low', 'high'], + ('low', 'high'), + np.array(['low', 'high'])] for label in label_arrays: fig, ax = plt.subplots() ax.plot(x, y, label=label) leg = ax.legend() - legend_texts = [entry.get_text() for entry in leg.get_texts()] - assert legend_texts == ['one', 'two', 'three'] + assert legend_texts == ['low', 'high'] def test_plot_multiple_input_single_label(): # test ax.plot() with multidimensional input # and single label - x = [1, 2, 5] - y = [[2, 4, 3], [4, 7, 1], [3, 9, 2]] + x = [1, 2, 3] + y = [[1, 2], + [2, 5], + [4, 9]] labels = ['one', 1, int] - for label in labels: fig, ax = plt.subplots() ax.plot(x, y, label=label) leg = ax.legend() - legend_texts = [entry.get_text() for entry in leg.get_texts()] - assert legend_texts == [str(label)] * 3 + assert legend_texts == [str(label)] * 2 def test_plot_single_input_multiple_label(): # test ax.plot() with 1D array like input # and iterable label - x = [1, 2, 5] - y = [2, 4, 3] - - label_arrays = [['one', 'two', 'three'], - ('one', 'two', 'three'), - np.array(['one', 'two', 'three'])] - + x = [1, 2, 3] + y = [2, 5, 6] + label_arrays = [['low', 'high'], + ('low', 'high'), + np.array(['low', 'high'])] for label in label_arrays: fig, ax = plt.subplots() ax.plot(x, y, label=label) leg = ax.legend() - assert len(leg.get_texts()) == 1 assert leg.get_texts()[0].get_text() == str(label) @@ -731,8 +727,10 @@ def test_plot_multiple_label_incorrect_length_exception(): # check that excepton is raised if multiple labels # are given, but number of on labels != number of lines with pytest.raises(ValueError): - x = [1, 2, 5] - y = [[2, 4, 3], [4, 7, 1], [3, 9, 2]] - label = ['one', 'two'] + x = [1, 2, 3] + y = [[1, 2], + [2, 5], + [4, 9]] + label = ['high', 'low', 'medium'] fig, ax = plt.subplots() ax.plot(x, y, label=label) From 73942be77c9c4eef374eaba8bca27865b7a79b48 Mon Sep 17 00:00:00 2001 From: yozhikoff Date: Fri, 10 Jul 2020 03:39:39 +0300 Subject: [PATCH 12/22] Remove unused imports --- lib/matplotlib/axes/_base.py | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index fe56dad187c4..fe8e0086aec8 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -1,5 +1,4 @@ from collections import OrderedDict -from collections.abc import Iterable from contextlib import ExitStack import functools import inspect From 9558099ef20740a04ba19a0b3025601447693b73 Mon Sep 17 00:00:00 2001 From: yozhikoff <35387375+yozhikoff@users.noreply.github.com> Date: Tue, 14 Jul 2020 21:31:25 +0300 Subject: [PATCH 13/22] Update multiple_labels_for_Axes_plot.rst --- doc/users/next_whats_new/multiple_labels_for_Axes_plot.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/users/next_whats_new/multiple_labels_for_Axes_plot.rst b/doc/users/next_whats_new/multiple_labels_for_Axes_plot.rst index 70dab44a22ec..1584357dc618 100644 --- a/doc/users/next_whats_new/multiple_labels_for_Axes_plot.rst +++ b/doc/users/next_whats_new/multiple_labels_for_Axes_plot.rst @@ -1,7 +1,9 @@ An iterable object with labels can be passed to `.Axes.plot` -------------------------------------------------------------- +------------------------------------------------------------ -When plotting multiple datasets by passing 2D data as *y* value to `~.Axes.plot`, labels for the datasets can be passed as a list, the length matching the number of columns in *y*. +When plotting multiple datasets by passing 2D data as *y* value to +`~.Axes.plot`, labels for the datasets can be passed as a list, the +length matching the number of columns in *y*. .. plot:: From 79c1b6315b310b069ce4ccfe933e067884a7c31f Mon Sep 17 00:00:00 2001 From: yozhikoff Date: Fri, 13 Nov 2020 17:43:13 +0300 Subject: [PATCH 14/22] Fix pep8 --- lib/matplotlib/axes/_base.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index fe8e0086aec8..6c441cdcad7a 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -459,8 +459,8 @@ def _plot_args(self, tup, kwargs, return_kwargs=False): labels = [label] * n_datasets result = (func(x[:, j % ncx], y[:, j % ncy], kw, - {**kwargs, 'label': label}) - for j, label in enumerate(labels)) + {**kwargs, 'label': label}) + for j, label in enumerate(labels)) if return_kwargs: return list(result) From 24325daadbcead7e184530abdf3e7a8adf2b89d0 Mon Sep 17 00:00:00 2001 From: yozhikoff Date: Wed, 23 Dec 2020 22:49:13 +0300 Subject: [PATCH 15/22] Use pytest.mark.parametrize --- lib/matplotlib/tests/test_legend.py | 51 +++++++++++++---------------- 1 file changed, 23 insertions(+), 28 deletions(-) diff --git a/lib/matplotlib/tests/test_legend.py b/lib/matplotlib/tests/test_legend.py index 57c8b67e2b09..75342bad2b31 100644 --- a/lib/matplotlib/tests/test_legend.py +++ b/lib/matplotlib/tests/test_legend.py @@ -673,54 +673,49 @@ def test_no_warn_big_data_when_loc_specified(): fig.draw_artist(legend) # Check that no warning is emitted. -def test_plot_multiple_input_multiple_label(): +@pytest.mark.parametrize('label_array', [['low', 'high'], ('low', 'high'), np.array(['low', 'high'])]) +def test_plot_multiple_input_multiple_label(label_array): # test ax.plot() with multidimensional input # and multiple labels x = [1, 2, 3] y = [[1, 2], [2, 5], [4, 9]] - label_arrays = [['low', 'high'], - ('low', 'high'), - np.array(['low', 'high'])] - for label in label_arrays: - fig, ax = plt.subplots() - ax.plot(x, y, label=label) - leg = ax.legend() - legend_texts = [entry.get_text() for entry in leg.get_texts()] - assert legend_texts == ['low', 'high'] + fig, ax = plt.subplots() + ax.plot(x, y, label=label_array) + leg = ax.legend() + legend_texts = [entry.get_text() for entry in leg.get_texts()] + assert legend_texts == ['low', 'high'] -def test_plot_multiple_input_single_label(): + +@pytest.mark.parametrize('label', ['one', 1, int]) +def test_plot_multiple_input_single_label(label): # test ax.plot() with multidimensional input # and single label x = [1, 2, 3] y = [[1, 2], [2, 5], [4, 9]] - labels = ['one', 1, int] - for label in labels: - fig, ax = plt.subplots() - ax.plot(x, y, label=label) - leg = ax.legend() - legend_texts = [entry.get_text() for entry in leg.get_texts()] - assert legend_texts == [str(label)] * 2 + fig, ax = plt.subplots() + ax.plot(x, y, label=label) + leg = ax.legend() + legend_texts = [entry.get_text() for entry in leg.get_texts()] + assert legend_texts == [str(label)] * 2 -def test_plot_single_input_multiple_label(): + +@pytest.mark.parametrize('label_array', [['low', 'high'], ('low', 'high'), np.array(['low', 'high'])]) +def test_plot_single_input_multiple_label(label_array): # test ax.plot() with 1D array like input # and iterable label x = [1, 2, 3] y = [2, 5, 6] - label_arrays = [['low', 'high'], - ('low', 'high'), - np.array(['low', 'high'])] - for label in label_arrays: - fig, ax = plt.subplots() - ax.plot(x, y, label=label) - leg = ax.legend() - assert len(leg.get_texts()) == 1 - assert leg.get_texts()[0].get_text() == str(label) + fig, ax = plt.subplots() + ax.plot(x, y, label=label_array) + leg = ax.legend() + assert len(leg.get_texts()) == 1 + assert leg.get_texts()[0].get_text() == str(label_array) def test_plot_multiple_label_incorrect_length_exception(): From 6bbd04e668fc4005a5595aa317d5d0b65095c05c Mon Sep 17 00:00:00 2001 From: yozhikoff Date: Wed, 23 Dec 2020 23:10:28 +0300 Subject: [PATCH 16/22] Fix pep8 --- lib/matplotlib/tests/test_legend.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/tests/test_legend.py b/lib/matplotlib/tests/test_legend.py index 75342bad2b31..cebf26ea066e 100644 --- a/lib/matplotlib/tests/test_legend.py +++ b/lib/matplotlib/tests/test_legend.py @@ -673,7 +673,9 @@ def test_no_warn_big_data_when_loc_specified(): fig.draw_artist(legend) # Check that no warning is emitted. -@pytest.mark.parametrize('label_array', [['low', 'high'], ('low', 'high'), np.array(['low', 'high'])]) +@pytest.mark.parametrize('label_array', [['low', 'high'], + ('low', 'high'), + np.array(['low', 'high'])]) def test_plot_multiple_input_multiple_label(label_array): # test ax.plot() with multidimensional input # and multiple labels @@ -705,7 +707,9 @@ def test_plot_multiple_input_single_label(label): assert legend_texts == [str(label)] * 2 -@pytest.mark.parametrize('label_array', [['low', 'high'], ('low', 'high'), np.array(['low', 'high'])]) +@pytest.mark.parametrize('label_array', [['low', 'high'], + ('low', 'high'), + np.array(['low', 'high'])]) def test_plot_single_input_multiple_label(label_array): # test ax.plot() with 1D array like input # and iterable label From 42883798dfb5853900225e55e9329a3f4d2afe2d Mon Sep 17 00:00:00 2001 From: yozhikoff Date: Thu, 24 Dec 2020 23:18:35 +0300 Subject: [PATCH 17/22] Raise exception in multiple data groups case --- lib/matplotlib/axes/_base.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index 6c441cdcad7a..e73ebc419a9c 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -293,6 +293,10 @@ def __call__(self, *args, data=None, **kwargs): replaced[label_namer_idx], args[label_namer_idx]) args = replaced + if len(args) >= 4 and not cbook.is_scalar_or_string(kwargs["label"]): + raise ValueError("plot() with multiple groups of data (i.e., pairs " + "of x and y) does not support multiple labels") + # Repeatedly grab (x, y) or (x, y, format) from the front of args and # massage them into arguments to plot() or fill(). From 143febfeff016c9dc605184818c86af7b2101664 Mon Sep 17 00:00:00 2001 From: yozhikoff Date: Thu, 24 Dec 2020 23:19:13 +0300 Subject: [PATCH 18/22] Add multiple label support to plot() docstring --- 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 9e6bee8a18a8..ead143489a3b 100644 --- a/lib/matplotlib/axes/_axes.py +++ b/lib/matplotlib/axes/_axes.py @@ -1499,6 +1499,8 @@ def plot(self, *args, scalex=True, scaley=True, data=None, **kwargs): If you make multiple lines with one plot call, the kwargs apply to all those lines. + In case if label object is iterable, each its element is + used as label for a separate line. Here is a list of available `.Line2D` properties: From 88ad403bd7ffdc68c23ad6f9ae592bc1ab0476ca Mon Sep 17 00:00:00 2001 From: yozhikoff Date: Thu, 24 Dec 2020 23:23:35 +0300 Subject: [PATCH 19/22] Fix line length --- lib/matplotlib/axes/_base.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index e73ebc419a9c..b2755b3d1ab2 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -294,8 +294,8 @@ def __call__(self, *args, data=None, **kwargs): args = replaced if len(args) >= 4 and not cbook.is_scalar_or_string(kwargs["label"]): - raise ValueError("plot() with multiple groups of data (i.e., pairs " - "of x and y) does not support multiple labels") + raise ValueError("plot() with multiple groups of data (i.e., pairs" + " of x and y) does not support multiple labels") # Repeatedly grab (x, y) or (x, y, format) from the front of args and # massage them into arguments to plot() or fill(). From 48ebde034cf14614b65d1f9c121b0978c78d3ae7 Mon Sep 17 00:00:00 2001 From: yozhikoff Date: Thu, 24 Dec 2020 23:24:47 +0300 Subject: [PATCH 20/22] Fix line length --- lib/matplotlib/axes/_base.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index b2755b3d1ab2..bcc89d84ac88 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -294,8 +294,9 @@ def __call__(self, *args, data=None, **kwargs): args = replaced if len(args) >= 4 and not cbook.is_scalar_or_string(kwargs["label"]): - raise ValueError("plot() with multiple groups of data (i.e., pairs" - " of x and y) does not support multiple labels") + raise ValueError("plot() with multiple groups of data (i.e., " + "pairs of x and y) does not support multiple " + "labels") # Repeatedly grab (x, y) or (x, y, format) from the front of args and # massage them into arguments to plot() or fill(). From afe34c5681568e3c8774a2147400e01b9a836141 Mon Sep 17 00:00:00 2001 From: yozhikoff Date: Thu, 24 Dec 2020 23:42:29 +0300 Subject: [PATCH 21/22] Fix missing label fail --- lib/matplotlib/axes/_base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index bcc89d84ac88..8bb877071af1 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -293,7 +293,7 @@ def __call__(self, *args, data=None, **kwargs): replaced[label_namer_idx], args[label_namer_idx]) args = replaced - if len(args) >= 4 and not cbook.is_scalar_or_string(kwargs["label"]): + if len(args) >= 4 and not cbook.is_scalar_or_string(kwargs.get("label")): raise ValueError("plot() with multiple groups of data (i.e., " "pairs of x and y) does not support multiple " "labels") From a161ae35c43447deb7d5b541b7967936d4f9f4d4 Mon Sep 17 00:00:00 2001 From: yozhikoff Date: Thu, 24 Dec 2020 23:45:45 +0300 Subject: [PATCH 22/22] Fix line length --- lib/matplotlib/axes/_base.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index 8bb877071af1..6692982ce0aa 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -293,7 +293,8 @@ def __call__(self, *args, data=None, **kwargs): replaced[label_namer_idx], args[label_namer_idx]) args = replaced - if len(args) >= 4 and not cbook.is_scalar_or_string(kwargs.get("label")): + if len(args) >= 4 and not cbook.is_scalar_or_string( + kwargs.get("label")): raise ValueError("plot() with multiple groups of data (i.e., " "pairs of x and y) does not support multiple " "labels") pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy