From 10770e97fe6cad0870a5aabaffa09a3e76f04a69 Mon Sep 17 00:00:00 2001 From: Jody Klymak Date: Sat, 31 Aug 2019 16:16:10 -0700 Subject: [PATCH 1/2] FIX: indexed pandas bar --- lib/matplotlib/axes/_axes.py | 23 +++++++++++++++++++++-- lib/matplotlib/tests/test_axes.py | 8 ++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py index 40e48fd5512f..0f2ed3593e4c 100644 --- a/lib/matplotlib/axes/_axes.py +++ b/lib/matplotlib/axes/_axes.py @@ -2140,12 +2140,31 @@ def _convert_dx(dx, x0, xconv, convert): try: x0 = x0[0] except (TypeError, IndexError, KeyError): - x0 = x0 + try: + xx = np.atleast_1d(np.asarray(x0)) + if len(xx) == 1: + # this keeps units for singletons... + x0 = x0 + else: + # fallback for objects with length, but strange + # ways of indexing (i.e. pandas) + x0 = xx[0] + except: + # generic except. Think this should never happen, but... + x0 = x0 try: x = xconv[0] except (TypeError, IndexError, KeyError): - x = xconv + try: + xx = np.atleast_1d(np.asarray(xconv)) + if len(xx) == 1: + x = xconv + else: + x = xx[0] + except: + # generic except. Think this should never happen, but... + x = xconv delist = False if not np.iterable(dx): diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index 01110ae26855..7830cde5f50d 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -1647,6 +1647,14 @@ def test_bar_pandas(pd): ax.plot(dates, baseline, color='orange', lw=4) +def test_bar_pandas_indexed(pd): + # Smoke test for indexed pandas + df = pd.DataFrame({"x": [1., 2., 3.], "width": [.2, .4, .6]}, + index=[1, 2, 3]) + fig, ax = plt.subplots() + ax.bar(df.x, 1., width=df.width) + + @image_comparison(['hist_log'], remove_text=True) def test_hist_log(): data0 = np.linspace(0, 1, 200)**3 From a023ecf16b1c3a9739a6c644876172b08d14a965 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Sun, 1 Sep 2019 12:49:23 -0400 Subject: [PATCH 2/2] MNT: simplify getting the first element Use `safe_first_element` from cbook which does the `next(iter(x))` dance to get the first element of an object (as defined by what you get when you iterate over it). --- lib/matplotlib/axes/_axes.py | 27 ++++----------------------- 1 file changed, 4 insertions(+), 23 deletions(-) diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py index 0f2ed3593e4c..a4afe5e83fdc 100644 --- a/lib/matplotlib/axes/_axes.py +++ b/lib/matplotlib/axes/_axes.py @@ -2138,33 +2138,14 @@ def _convert_dx(dx, x0, xconv, convert): # removes the units from unit packages like `pint` that # wrap numpy arrays. try: - x0 = x0[0] + x0 = cbook.safe_first_element(x0) except (TypeError, IndexError, KeyError): - try: - xx = np.atleast_1d(np.asarray(x0)) - if len(xx) == 1: - # this keeps units for singletons... - x0 = x0 - else: - # fallback for objects with length, but strange - # ways of indexing (i.e. pandas) - x0 = xx[0] - except: - # generic except. Think this should never happen, but... - x0 = x0 + x0 = x0 try: - x = xconv[0] + x = cbook.safe_first_element(xconv) except (TypeError, IndexError, KeyError): - try: - xx = np.atleast_1d(np.asarray(xconv)) - if len(xx) == 1: - x = xconv - else: - x = xx[0] - except: - # generic except. Think this should never happen, but... - x = xconv + x = xconv delist = False if not np.iterable(dx):