Skip to content

Commit 40e19bb

Browse files
BUG: Respect color argument in bar plot (#17360)
This affect Series-like barplots with user-defined colors. We were always treating them as dataframe-like, with one color per column.
1 parent f5cfdbb commit 40e19bb

File tree

4 files changed

+33
-1
lines changed

4 files changed

+33
-1
lines changed

doc/source/whatsnew/v0.21.0.txt

+2
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,8 @@ Plotting
524524
^^^^^^^^
525525
- Bug in plotting methods using ``secondary_y`` and ``fontsize`` not setting secondary axis font size (:issue:`12565`)
526526
- Bug when plotting ``timedelta`` and ``datetime`` dtypes on y-axis (:issue:`16953`)
527+
- Bug in ``Series.plot.bar`` or ``DataFramee.plot.bar`` with ``y`` not respecting user-passed ``color`` (:issue:`16822`)
528+
527529

528530
Groupby/Resample/Rolling
529531
^^^^^^^^^^^^^^^^^^^^^^^^

pandas/plotting/_core.py

+7-1
Original file line numberDiff line numberDiff line change
@@ -1150,6 +1150,9 @@ class BarPlot(MPLPlot):
11501150
orientation = 'vertical'
11511151

11521152
def __init__(self, data, **kwargs):
1153+
# we have to treat a series differently than a
1154+
# 1-column DataFrame w.r.t. color handling
1155+
self._is_series = isinstance(data, ABCSeries)
11531156
self.bar_width = kwargs.pop('width', 0.5)
11541157
pos = kwargs.pop('position', 0.5)
11551158
kwargs.setdefault('align', 'center')
@@ -1204,7 +1207,10 @@ def _make_plot(self):
12041207
for i, (label, y) in enumerate(self._iter_data(fillna=0)):
12051208
ax = self._get_ax(i)
12061209
kwds = self.kwds.copy()
1207-
kwds['color'] = colors[i % ncolors]
1210+
if self._is_series:
1211+
kwds['color'] = colors
1212+
else:
1213+
kwds['color'] = colors[i % ncolors]
12081214

12091215
errors = self._get_errorbars(label=label, index=i)
12101216
kwds = dict(kwds, **errors)

pandas/tests/plotting/test_frame.py

+14
Original file line numberDiff line numberDiff line change
@@ -807,6 +807,20 @@ def test_bar_colors(self):
807807
self._check_colors(ax.patches[::5], facecolors=['green'] * 5)
808808
tm.close()
809809

810+
def test_bar_user_colors(self):
811+
df = pd.DataFrame({"A": range(4),
812+
"B": range(1, 5),
813+
"color": ['red', 'blue', 'blue', 'red']})
814+
# This should *only* work when `y` is specified, else
815+
# we use one color per column
816+
ax = df.plot.bar(y='A', color=df['color'])
817+
result = [p.get_facecolor() for p in ax.patches]
818+
expected = [(1., 0., 0., 1.),
819+
(0., 0., 1., 1.),
820+
(0., 0., 1., 1.),
821+
(1., 0., 0., 1.)]
822+
assert result == expected
823+
810824
@pytest.mark.slow
811825
def test_bar_linewidth(self):
812826
df = DataFrame(randn(5, 5))

pandas/tests/plotting/test_series.py

+10
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,16 @@ def test_bar_ignore_index(self):
258258
ax = df.plot.bar(use_index=False, ax=ax)
259259
self._check_text_labels(ax.get_xticklabels(), ['0', '1', '2', '3'])
260260

261+
def test_bar_user_colors(self):
262+
s = Series([1, 2, 3, 4])
263+
ax = s.plot.bar(color=['red', 'blue', 'blue', 'red'])
264+
result = [p.get_facecolor() for p in ax.patches]
265+
expected = [(1., 0., 0., 1.),
266+
(0., 0., 1., 1.),
267+
(0., 0., 1., 1.),
268+
(1., 0., 0., 1.)]
269+
assert result == expected
270+
261271
def test_rotation(self):
262272
df = DataFrame(randn(5, 5))
263273
# Default rot 0

0 commit comments

Comments
 (0)