diff --git a/doc/source/v0.15.0.txt b/doc/source/v0.15.0.txt index 5e3f97944c243..5edc337a1c6a5 100644 --- a/doc/source/v0.15.0.txt +++ b/doc/source/v0.15.0.txt @@ -199,6 +199,7 @@ Bug Fixes +- Bug in ``DataFrame.plot`` with ``subplots=True`` may draw unnecessary minor xticks and yticks (:issue:`7801`) diff --git a/pandas/tests/test_graphics.py b/pandas/tests/test_graphics.py index 00045e88ba2f0..f9ae058c065e3 100644 --- a/pandas/tests/test_graphics.py +++ b/pandas/tests/test_graphics.py @@ -126,11 +126,14 @@ def _check_visible(self, collections, visible=True): Parameters ---------- - collections : list-like - list or collection of target artist + collections : matplotlib Artist or its list-like + target Artist or its list or collection visible : bool expected visibility """ + from matplotlib.collections import Collection + if not isinstance(collections, Collection) and not com.is_list_like(collections): + collections = [collections] for patch in collections: self.assertEqual(patch.get_visible(), visible) @@ -861,9 +864,12 @@ def test_plot(self): axes = _check_plot_works(df.plot, subplots=True, title='blah') self._check_axes_shape(axes, axes_num=3, layout=(3, 1)) for ax in axes[:2]: + self._check_visible(ax.xaxis) # xaxis must be visible for grid self._check_visible(ax.get_xticklabels(), visible=False) + self._check_visible(ax.get_xticklabels(minor=True), visible=False) self._check_visible([ax.xaxis.get_label()], visible=False) for ax in [axes[2]]: + self._check_visible(ax.xaxis) self._check_visible(ax.get_xticklabels()) self._check_visible([ax.xaxis.get_label()]) @@ -1017,21 +1023,61 @@ def test_subplots(self): self._check_legend_labels(ax, labels=[com.pprint_thing(column)]) for ax in axes[:-2]: + self._check_visible(ax.xaxis) # xaxis must be visible for grid self._check_visible(ax.get_xticklabels(), visible=False) + self._check_visible(ax.get_xticklabels(minor=True), visible=False) + self._check_visible(ax.xaxis.get_label(), visible=False) self._check_visible(ax.get_yticklabels()) + self._check_visible(axes[-1].xaxis) self._check_visible(axes[-1].get_xticklabels()) + self._check_visible(axes[-1].get_xticklabels(minor=True)) + self._check_visible(axes[-1].xaxis.get_label()) self._check_visible(axes[-1].get_yticklabels()) axes = df.plot(kind=kind, subplots=True, sharex=False) for ax in axes: + self._check_visible(ax.xaxis) self._check_visible(ax.get_xticklabels()) + self._check_visible(ax.get_xticklabels(minor=True)) + self._check_visible(ax.xaxis.get_label()) self._check_visible(ax.get_yticklabels()) axes = df.plot(kind=kind, subplots=True, legend=False) for ax in axes: self.assertTrue(ax.get_legend() is None) + @slow + def test_subplots_timeseries(self): + idx = date_range(start='2014-07-01', freq='M', periods=10) + df = DataFrame(np.random.rand(10, 3), index=idx) + + for kind in ['line', 'area']: + axes = df.plot(kind=kind, subplots=True, sharex=True) + self._check_axes_shape(axes, axes_num=3, layout=(3, 1)) + + for ax in axes[:-2]: + # GH 7801 + self._check_visible(ax.xaxis) # xaxis must be visible for grid + self._check_visible(ax.get_xticklabels(), visible=False) + self._check_visible(ax.get_xticklabels(minor=True), visible=False) + self._check_visible(ax.xaxis.get_label(), visible=False) + self._check_visible(ax.get_yticklabels()) + + self._check_visible(axes[-1].xaxis) + self._check_visible(axes[-1].get_xticklabels()) + self._check_visible(axes[-1].get_xticklabels(minor=True)) + self._check_visible(axes[-1].xaxis.get_label()) + self._check_visible(axes[-1].get_yticklabels()) + + axes = df.plot(kind=kind, subplots=True, sharex=False) + for ax in axes: + self._check_visible(ax.xaxis) + self._check_visible(ax.get_xticklabels()) + self._check_visible(ax.get_xticklabels(minor=True)) + self._check_visible(ax.xaxis.get_label()) + self._check_visible(ax.get_yticklabels()) + def test_negative_log(self): df = - DataFrame(rand(6, 4), index=list(string.ascii_letters[:6]), diff --git a/pandas/tools/plotting.py b/pandas/tools/plotting.py index d3ea809b79b76..3570b605c714e 100644 --- a/pandas/tools/plotting.py +++ b/pandas/tools/plotting.py @@ -2972,16 +2972,35 @@ def _subplots(nrows=1, ncols=1, naxes=None, sharex=False, sharey=False, squeeze= axarr[i] = ax if nplots > 1: + if sharex and nrows > 1: for ax in axarr[:naxes][:-ncols]: # only bottom row for label in ax.get_xticklabels(): label.set_visible(False) + try: + # set_visible will not be effective if + # minor axis has NullLocator and NullFormattor (default) + import matplotlib.ticker as ticker + ax.xaxis.set_minor_locator(ticker.AutoLocator()) + ax.xaxis.set_minor_formatter(ticker.FormatStrFormatter('')) + for label in ax.get_xticklabels(minor=True): + label.set_visible(False) + except Exception: # pragma no cover + pass ax.xaxis.get_label().set_visible(False) if sharey and ncols > 1: for i, ax in enumerate(axarr): if (i % ncols) != 0: # only first column for label in ax.get_yticklabels(): label.set_visible(False) + try: + import matplotlib.ticker as ticker + ax.yaxis.set_minor_locator(ticker.AutoLocator()) + ax.yaxis.set_minor_formatter(ticker.FormatStrFormatter('')) + for label in ax.get_yticklabels(minor=True): + label.set_visible(False) + except Exception: # pragma no cover + pass ax.yaxis.get_label().set_visible(False) if naxes != nplots: