Skip to content
Closed
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/source/whatsnew/v3.0.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -798,6 +798,7 @@ Plotting
- 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`)
- Bug in :meth:`DataFrame.plot.line` raising ``ValueError`` when set both color and a ``dict`` style (:issue:`59461`)
- Bug in :meth:`DataFrame.plot` that causes a shift to the right when the frequency multiplier is greater than one. (:issue:`57587`)
- 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`)
- Bug in :meth:`Series.plot` preventing a line and bar from being aligned on the same plot (:issue:`61161`)
- Bug in :meth:`Series.plot` preventing a line and scatter plot from being aligned (:issue:`61005`)
- Bug in :meth:`Series.plot` with ``kind="pie"`` with :class:`ArrowDtype` (:issue:`59192`)
Expand Down
4 changes: 2 additions & 2 deletions pandas/plotting/_matplotlib/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -1365,7 +1365,7 @@ def _make_plot(self, fig: Figure) -> None:
# if a list of non-color strings is passed in as c, color points
# by uniqueness of the strings, such same strings get same color
create_colors = not self._are_valid_colors(c_values)
if create_colors:
if c_values is not None and create_colors:
color_mapping = self._get_color_mapping(c_values)
c_values = [color_mapping[s] for s in c_values]

Expand Down Expand Up @@ -1416,7 +1416,7 @@ def _get_c_values(self, color, color_by_categorical: bool, c_is_column: bool):
if c is not None and color is not None:
raise TypeError("Specify exactly one of `c` and `color`")
if c is None and color is None:
c_values = mpl.rcParams["patch.facecolor"]
c_values = None
elif color is not None:
c_values = color
elif color_by_categorical:
Expand Down
49 changes: 49 additions & 0 deletions pandas/tests/plotting/test_groupby.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,3 +152,52 @@ def test_groupby_hist_series_with_legend_raises(self):

with pytest.raises(ValueError, match="Cannot use both legend and label"):
g.hist(legend=True, label="d")

def test_groupby_scatter_colors_differ(self):
# GH 59846 - Test that scatter plots use different colors for different groups
# similar to how line plots do
from matplotlib.collections import PathCollection
import matplotlib.pyplot as plt

# Create test data with distinct groups
df = DataFrame(
{
"x": [1, 2, 3, 4, 5, 6, 7, 8, 9],
"y": [1, 2, 3, 4, 5, 6, 7, 8, 9],
"group": ["A", "A", "A", "B", "B", "B", "C", "C", "C"],
}
)

# Set up a figure with both line and scatter plots
fig, (ax1, ax2) = plt.subplots(1, 2)

# Plot line chart (known to use different colors for different groups)
df.groupby("group").plot(x="x", y="y", ax=ax1, kind="line")

# Plot scatter chart (should also use different colors for different groups)
df.groupby("group").plot(x="x", y="y", ax=ax2, kind="scatter")

# Get the colors used in the line plot and scatter plot
line_colors = [line.get_color() for line in ax1.get_lines()]

# Get scatter colors
scatter_colors = []
for collection in ax2.collections:
if isinstance(collection, PathCollection): # This is a scatter plot
# Get the face colors (might be array of RGBA values)
face_colors = collection.get_facecolor()
# If multiple points with same color, we get the first one
if face_colors.ndim > 1:
scatter_colors.append(tuple(face_colors[0]))
else:
scatter_colors.append(tuple(face_colors))

# Assert that we have the right number of colors (one per group)
assert len(line_colors) == 3
assert len(scatter_colors) == 3

# Assert that the colors are all different
assert len(set(scatter_colors)) == 3
assert len(line_colors) == 3

plt.close(fig)
Loading