Skip to content

Commit 7509aed

Browse files
PLT: Color attributes of medianprops etc are lost in df.boxplot and df.plot.boxplot (#31262)
1 parent 50ebb24 commit 7509aed

File tree

4 files changed

+58
-10
lines changed

4 files changed

+58
-10
lines changed

doc/source/whatsnew/v1.1.0.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,8 @@ Plotting
192192

193193
- :func:`.plot` for line/bar now accepts color by dictonary (:issue:`8193`).
194194
-
195+
- Bug in :meth:`DataFrame.boxplot` and :meth:`DataFrame.plot.boxplot` lost color attributes of ``medianprops``, ``whiskerprops``, ``capprops`` and ``medianprops`` (:issue:`30346`)
196+
195197

196198
Groupby/resample/rolling
197199
^^^^^^^^^^^^^^^^^^^^^^^^

pandas/plotting/_matplotlib/boxplot.py

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -107,10 +107,16 @@ def maybe_color_bp(self, bp):
107107
medians = self.color or self._medians_c
108108
caps = self.color or self._caps_c
109109

110-
setp(bp["boxes"], color=boxes, alpha=1)
111-
setp(bp["whiskers"], color=whiskers, alpha=1)
112-
setp(bp["medians"], color=medians, alpha=1)
113-
setp(bp["caps"], color=caps, alpha=1)
110+
# GH 30346, when users specifying those arguments explicitly, our defaults
111+
# for these four kwargs should be overridden; if not, use Pandas settings
112+
if not self.kwds.get("boxprops"):
113+
setp(bp["boxes"], color=boxes, alpha=1)
114+
if not self.kwds.get("whiskerprops"):
115+
setp(bp["whiskers"], color=whiskers, alpha=1)
116+
if not self.kwds.get("medianprops"):
117+
setp(bp["medians"], color=medians, alpha=1)
118+
if not self.kwds.get("capprops"):
119+
setp(bp["caps"], color=caps, alpha=1)
114120

115121
def _make_plot(self):
116122
if self.subplots:
@@ -275,11 +281,17 @@ def _get_colors():
275281

276282
return result
277283

278-
def maybe_color_bp(bp):
279-
setp(bp["boxes"], color=colors[0], alpha=1)
280-
setp(bp["whiskers"], color=colors[1], alpha=1)
281-
setp(bp["medians"], color=colors[2], alpha=1)
282-
setp(bp["caps"], color=colors[3], alpha=1)
284+
def maybe_color_bp(bp, **kwds):
285+
# GH 30346, when users specifying those arguments explicitly, our defaults
286+
# for these four kwargs should be overridden; if not, use Pandas settings
287+
if not kwds.get("boxprops"):
288+
setp(bp["boxes"], color=colors[0], alpha=1)
289+
if not kwds.get("whiskerprops"):
290+
setp(bp["whiskers"], color=colors[1], alpha=1)
291+
if not kwds.get("medianprops"):
292+
setp(bp["medians"], color=colors[2], alpha=1)
293+
if not kwds.get("capprops"):
294+
setp(bp["caps"], color=colors[3], alpha=1)
283295

284296
def plot_group(keys, values, ax):
285297
keys = [pprint_thing(x) for x in keys]
@@ -291,7 +303,7 @@ def plot_group(keys, values, ax):
291303
ax.set_xticklabels(keys, rotation=rot)
292304
else:
293305
ax.set_yticklabels(keys, rotation=rot)
294-
maybe_color_bp(bp)
306+
maybe_color_bp(bp, **kwds)
295307

296308
# Return axes in multiplot case, maybe revisit later # 985
297309
if return_type == "dict":

pandas/tests/plotting/test_boxplot_method.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,23 @@ def test_color_kwd_errors(self, dict_colors, msg):
203203
with pytest.raises(ValueError, match=msg):
204204
df.boxplot(color=dict_colors, return_type="dict")
205205

206+
@pytest.mark.parametrize(
207+
"props, expected",
208+
[
209+
("boxprops", "boxes"),
210+
("whiskerprops", "whiskers"),
211+
("capprops", "caps"),
212+
("medianprops", "medians"),
213+
],
214+
)
215+
def test_specified_props_kwd(self, props, expected):
216+
# GH 30346
217+
df = DataFrame({k: np.random.random(100) for k in "ABC"})
218+
kwd = {props: dict(color="C1")}
219+
result = df.boxplot(return_type="dict", **kwd)
220+
221+
assert result[expected][0].get_color() == "C1"
222+
206223

207224
@td.skip_if_no_mpl
208225
class TestDataFrameGroupByPlots(TestPlotBase):

pandas/tests/plotting/test_frame.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2352,6 +2352,23 @@ def _check_colors(bp, box_c, whiskers_c, medians_c, caps_c="k", fliers_c=None):
23522352
# Color contains invalid key results in ValueError
23532353
df.plot.box(color=dict(boxes="red", xxxx="blue"))
23542354

2355+
@pytest.mark.parametrize(
2356+
"props, expected",
2357+
[
2358+
("boxprops", "boxes"),
2359+
("whiskerprops", "whiskers"),
2360+
("capprops", "caps"),
2361+
("medianprops", "medians"),
2362+
],
2363+
)
2364+
def test_specified_props_kwd_plot_box(self, props, expected):
2365+
# GH 30346
2366+
df = DataFrame({k: np.random.random(100) for k in "ABC"})
2367+
kwd = {props: dict(color="C1")}
2368+
result = df.plot.box(return_type="dict", **kwd)
2369+
2370+
assert result[expected][0].get_color() == "C1"
2371+
23552372
def test_default_color_cycle(self):
23562373
import matplotlib.pyplot as plt
23572374
import cycler

0 commit comments

Comments
 (0)