diff --git a/doc/source/whatsnew/v0.24.0.txt b/doc/source/whatsnew/v0.24.0.txt index d7feb6e547b22..e363c77710d70 100644 --- a/doc/source/whatsnew/v0.24.0.txt +++ b/doc/source/whatsnew/v0.24.0.txt @@ -683,6 +683,7 @@ Plotting - Bug in :func:`DataFrame.plot.scatter` and :func:`DataFrame.plot.hexbin` caused x-axis label and ticklabels to disappear when colorbar was on in IPython inline backend (:issue:`10611`, :issue:`10678`, and :issue:`20455`) - Bug in plotting a Series with datetimes using :func:`matplotlib.axes.Axes.scatter` (:issue:`22039`) +- Bug in colors selection in :func:`DataFrame.plot.bar` which causes different colors to be used when no color is specified (:issue:`20585`) Groupby/Resample/Rolling ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/pandas/plotting/_core.py b/pandas/plotting/_core.py index 4fa3b51c60ee4..0d4a485e52d68 100644 --- a/pandas/plotting/_core.py +++ b/pandas/plotting/_core.py @@ -1233,6 +1233,16 @@ def _plot(cls, ax, x, y, w, start=0, log=False, **kwds): def _start_base(self): return self.bottom + def _get_colors(self, num_colors=None, color_kwds='color'): + color = self.kwds.get(color_kwds) + if color is not None: + return color + else: + num_colors = self.nseries + return _get_standard_colors(num_colors=num_colors, + colormap=self.colormap, + color=self.kwds.get(color_kwds)) + def _make_plot(self): import matplotlib as mpl diff --git a/pandas/plotting/_style.py b/pandas/plotting/_style.py index c72e092c73aa2..de90d51aa933d 100644 --- a/pandas/plotting/_style.py +++ b/pandas/plotting/_style.py @@ -91,7 +91,9 @@ def _maybe_valid_colors(colors): # mpl will raise error any of them is invalid pass - if len(colors) != num_colors: + if len(colors) > num_colors: + colors = colors[:num_colors] + elif len(colors) < num_colors: try: multiple = num_colors // len(colors) - 1 except ZeroDivisionError: diff --git a/pandas/tests/plotting/test_series.py b/pandas/tests/plotting/test_series.py index 5dc7d52e05778..6c15f2101c009 100644 --- a/pandas/tests/plotting/test_series.py +++ b/pandas/tests/plotting/test_series.py @@ -21,6 +21,7 @@ from pandas.tests.plotting.common import (TestPlotBase, _check_plot_works, _skip_if_no_scipy_gaussian_kde, _ok_for_gaussian_kde) +from pandas.plotting._style import _get_standard_colors @td.skip_if_no_mpl @@ -268,6 +269,36 @@ def test_bar_user_colors(self): (1., 0., 0., 1.)] assert result == expected + def test_bar_user_colors_limited(self): + # GH 20585 + s = Series([1, 2, 3, 4]) + ax = s.plot.bar(color=['red', 'blue']) + result = [p.get_facecolor() for p in ax.patches] + expected = [(1., 0., 0., 1.), + (0., 0., 1., 1.), + (1., 0., 0., 1.), + (0., 0., 1., 1.)] + assert result == expected + + def test_bar_user_colors_more_limited(self): + s = Series([1, 2, 3, 4, 5, 6]) + ax = s.plot.bar(color=['red', 'blue']) + result = [p.get_facecolor() for p in ax.patches] + expected = [(1., 0., 0., 1.), + (0., 0., 1., 1.), + (1., 0., 0., 1.), + (0., 0., 1., 1.), + (1., 0., 0., 1.), + (0., 0., 1., 1.)] + assert result == expected + + @pytest.mark.parametrize("num_colors",range(0,15)) + def test_standard_color(self, num_colors): + # GH 20585 + colors = _get_standard_colors(num_colors=num_colors) + + assert len(colors) == num_colors + def test_rotation(self): df = DataFrame(randn(5, 5)) # Default rot 0