From 7b202468ac6ab0a0dda38a3792e6c101d4e1b3dc Mon Sep 17 00:00:00 2001 From: Christoph Boeddeker Date: Mon, 11 Dec 2017 13:48:11 +0100 Subject: [PATCH 1/6] bugfix for plot for string x values --- pandas/plotting/_core.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pandas/plotting/_core.py b/pandas/plotting/_core.py index b15c5271ae321..0be1423f73420 100644 --- a/pandas/plotting/_core.py +++ b/pandas/plotting/_core.py @@ -573,6 +573,8 @@ def _get_xticks(self, convert_period=False): self.data = self.data[notna(self.data.index)] self.data = self.data.sort_index() x = self.data.index._mpl_repr() + elif all(isinstance(val, str) for val in index): + x = index._mpl_repr() else: self._need_to_set_index = True x = lrange(len(index)) From 7f88d828f445feb4450a95555c212bf5cbd2af54 Mon Sep 17 00:00:00 2001 From: Christoph Date: Mon, 11 Dec 2017 21:54:00 +0100 Subject: [PATCH 2/6] fix backward compatibility for str check --- pandas/plotting/_core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/plotting/_core.py b/pandas/plotting/_core.py index 0be1423f73420..63551bbea6be6 100644 --- a/pandas/plotting/_core.py +++ b/pandas/plotting/_core.py @@ -573,7 +573,7 @@ def _get_xticks(self, convert_period=False): self.data = self.data[notna(self.data.index)] self.data = self.data.sort_index() x = self.data.index._mpl_repr() - elif all(isinstance(val, str) for val in index): + elif all(isinstance(val, string_types) for val in index): x = index._mpl_repr() else: self._need_to_set_index = True From f3308314a15980f886f1191c3344366a586811c7 Mon Sep 17 00:00:00 2001 From: Christoph Date: Tue, 12 Dec 2017 10:35:09 +0100 Subject: [PATCH 3/6] use index.inferred_type for string test --- pandas/plotting/_core.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pandas/plotting/_core.py b/pandas/plotting/_core.py index 63551bbea6be6..9ef7503bd9d59 100644 --- a/pandas/plotting/_core.py +++ b/pandas/plotting/_core.py @@ -561,20 +561,22 @@ def _get_xticks(self, convert_period=False): if convert_period and isinstance(index, PeriodIndex): self.data = self.data.reindex(index=index.sort_values()) x = self.data.index.to_timestamp()._mpl_repr() - elif index.is_numeric(): + elif (index.is_numeric() or + index.inferred_type in ['string', 'unicode'] + ): """ Matplotlib supports numeric values or datetime objects as xaxis values. Taking LBYL approach here, by the time matplotlib raises exception when using non numeric/datetime values for xaxis, several actions are already taken by plt. + + Matplotlib also supports strings as xaxis values. """ x = index._mpl_repr() elif is_datetype: self.data = self.data[notna(self.data.index)] self.data = self.data.sort_index() x = self.data.index._mpl_repr() - elif all(isinstance(val, string_types) for val in index): - x = index._mpl_repr() else: self._need_to_set_index = True x = lrange(len(index)) From ca311b539a3264f61e5890afe652c08bae64888b Mon Sep 17 00:00:00 2001 From: Christoph Date: Tue, 12 Dec 2017 10:35:31 +0100 Subject: [PATCH 4/6] add test --- pandas/tests/plotting/test_frame.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/pandas/tests/plotting/test_frame.py b/pandas/tests/plotting/test_frame.py index 3d25b0b51e052..41ea99439d04a 100644 --- a/pandas/tests/plotting/test_frame.py +++ b/pandas/tests/plotting/test_frame.py @@ -139,6 +139,23 @@ def test_plot(self): result = ax.get_axes() # deprecated assert result is axes[0] + # GH 18726 + def test_two_plots_with_x_str(self): + x1, y1 = ['a', 'b'], [1, 2] + x2, y2 = ['b', 'a'], [4, 3] + df1 = pd.DataFrame(y1, index=x1) + df2 = pd.DataFrame(y2, index=x2) + ax = None + ax = df1.plot(ax=ax) + ax = df2.plot(ax=ax) + + line1, line2 = ax.lines + # xdata should not be touched (Earlier it was [0, 1]) + np.testing.assert_equal(line1.get_xdata(), x1) + np.testing.assert_equal(line1.get_ydata(), y1) + np.testing.assert_equal(line2.get_xdata(), x2) + np.testing.assert_equal(line2.get_ydata(), y2) + # GH 15516 def test_mpl2_color_cycle_str(self): # test CN mpl 2.0 color cycle From 81db89608a83884c501f3730b73621fae6712389 Mon Sep 17 00:00:00 2001 From: Christoph Date: Tue, 12 Dec 2017 10:37:01 +0100 Subject: [PATCH 5/6] pep8 --- pandas/plotting/_core.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pandas/plotting/_core.py b/pandas/plotting/_core.py index 9ef7503bd9d59..3e186b7e4aaee 100644 --- a/pandas/plotting/_core.py +++ b/pandas/plotting/_core.py @@ -562,14 +562,12 @@ def _get_xticks(self, convert_period=False): self.data = self.data.reindex(index=index.sort_values()) x = self.data.index.to_timestamp()._mpl_repr() elif (index.is_numeric() or - index.inferred_type in ['string', 'unicode'] - ): + index.inferred_type in ['string', 'unicode']): """ Matplotlib supports numeric values or datetime objects as xaxis values. Taking LBYL approach here, by the time matplotlib raises exception when using non numeric/datetime values for xaxis, several actions are already taken by plt. - Matplotlib also supports strings as xaxis values. """ x = index._mpl_repr() From 5b48a03abf45e3b20b253d552088f21d265467f5 Mon Sep 17 00:00:00 2001 From: Christoph Date: Wed, 13 Dec 2017 10:01:42 +0100 Subject: [PATCH 6/6] review --- pandas/tests/plotting/test_frame.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/pandas/tests/plotting/test_frame.py b/pandas/tests/plotting/test_frame.py index 41ea99439d04a..6dcd342b94a47 100644 --- a/pandas/tests/plotting/test_frame.py +++ b/pandas/tests/plotting/test_frame.py @@ -150,11 +150,16 @@ def test_two_plots_with_x_str(self): ax = df2.plot(ax=ax) line1, line2 = ax.lines + # xdata should not be touched (Earlier it was [0, 1]) - np.testing.assert_equal(line1.get_xdata(), x1) - np.testing.assert_equal(line1.get_ydata(), y1) - np.testing.assert_equal(line2.get_xdata(), x2) - np.testing.assert_equal(line2.get_ydata(), y2) + tm.assert_numpy_array_equal(line1.get_xdata(), np.array(x1), + check_dtype=False) + tm.assert_numpy_array_equal(line1.get_ydata(), np.array(y1), + check_dtype=False) + tm.assert_numpy_array_equal(line2.get_xdata(), np.array(x2), + check_dtype=False) + tm.assert_numpy_array_equal(line2.get_ydata(), np.array(y2), + check_dtype=False) # GH 15516 def test_mpl2_color_cycle_str(self):