Skip to content

Commit ce37450

Browse files
committed
BUG: Fix scatter plot colors in groupby context to match line plot behavior (#59846)
1 parent 3e8a878 commit ce37450

File tree

3 files changed

+52
-2
lines changed

3 files changed

+52
-2
lines changed

doc/source/whatsnew/v3.0.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -763,6 +763,7 @@ Plotting
763763
- Bug in :meth:`DataFrame.plot.bar` with ``stacked=True`` where labels on stacked bars with zero-height segments were incorrectly positioned at the base instead of the label position of the previous segment (:issue:`59429`)
764764
- Bug in :meth:`DataFrame.plot.line` raising ``ValueError`` when set both color and a ``dict`` style (:issue:`59461`)
765765
- Bug in :meth:`DataFrame.plot` that causes a shift to the right when the frequency multiplier is greater than one. (:issue:`57587`)
766+
- Bug in :meth:`DataFrameGroupBy.plot` with ``kind="scatter"`` where all groups used the same color instead of different colors for each group like line plots do (:issue:`59846`)
766767
- Bug in :meth:`Series.plot` preventing a line and scatter plot from being aligned (:issue:`61005`)
767768
- Bug in :meth:`Series.plot` with ``kind="pie"`` with :class:`ArrowDtype` (:issue:`59192`)
768769

pandas/plotting/_matplotlib/core.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -1371,7 +1371,7 @@ def _make_plot(self, fig: Figure) -> None:
13711371
# if a list of non-color strings is passed in as c, color points
13721372
# by uniqueness of the strings, such same strings get same color
13731373
create_colors = not self._are_valid_colors(c_values)
1374-
if create_colors:
1374+
if c_values is not None and create_colors:
13751375
color_mapping = self._get_color_mapping(c_values)
13761376
c_values = [color_mapping[s] for s in c_values]
13771377

@@ -1422,7 +1422,7 @@ def _get_c_values(self, color, color_by_categorical: bool, c_is_column: bool):
14221422
if c is not None and color is not None:
14231423
raise TypeError("Specify exactly one of `c` and `color`")
14241424
if c is None and color is None:
1425-
c_values = mpl.rcParams["patch.facecolor"]
1425+
c_values = None
14261426
elif color is not None:
14271427
c_values = color
14281428
elif color_by_categorical:

pandas/tests/plotting/test_groupby.py

+49
Original file line numberDiff line numberDiff line change
@@ -152,3 +152,52 @@ def test_groupby_hist_series_with_legend_raises(self):
152152

153153
with pytest.raises(ValueError, match="Cannot use both legend and label"):
154154
g.hist(legend=True, label="d")
155+
156+
def test_groupby_scatter_colors_differ(self):
157+
# GH 59846 - Test that scatter plots use different colors for different groups
158+
# similar to how line plots do
159+
from matplotlib.collections import PathCollection
160+
import matplotlib.pyplot as plt
161+
162+
# Create test data with distinct groups
163+
df = DataFrame(
164+
{
165+
"x": [1, 2, 3, 4, 5, 6, 7, 8, 9],
166+
"y": [1, 2, 3, 4, 5, 6, 7, 8, 9],
167+
"group": ["A", "A", "A", "B", "B", "B", "C", "C", "C"],
168+
}
169+
)
170+
171+
# Set up a figure with both line and scatter plots
172+
fig, (ax1, ax2) = plt.subplots(1, 2)
173+
174+
# Plot line chart (known to use different colors for different groups)
175+
df.groupby("group").plot(x="x", y="y", ax=ax1, kind="line")
176+
177+
# Plot scatter chart (should also use different colors for different groups)
178+
df.groupby("group").plot(x="x", y="y", ax=ax2, kind="scatter")
179+
180+
# Get the colors used in the line plot and scatter plot
181+
line_colors = [line.get_color() for line in ax1.get_lines()]
182+
183+
# Get scatter colors
184+
scatter_colors = []
185+
for collection in ax2.collections:
186+
if isinstance(collection, PathCollection): # This is a scatter plot
187+
# Get the face colors (might be array of RGBA values)
188+
face_colors = collection.get_facecolor()
189+
# If multiple points with same color, we get the first one
190+
if face_colors.ndim > 1:
191+
scatter_colors.append(tuple(face_colors[0]))
192+
else:
193+
scatter_colors.append(tuple(face_colors))
194+
195+
# Assert that we have the right number of colors (one per group)
196+
assert len(line_colors) == 3
197+
assert len(scatter_colors) == 3
198+
199+
# Assert that the colors are all different
200+
assert len(set(scatter_colors)) == 3
201+
assert len(line_colors) == 3
202+
203+
plt.close(fig)

0 commit comments

Comments
 (0)