diff --git a/doc/api/next_api_changes/behavior/10008-HK.rst b/doc/api/next_api_changes/behavior/10008-HK.rst new file mode 100644 index 000000000000..8ac9709403b8 --- /dev/null +++ b/doc/api/next_api_changes/behavior/10008-HK.rst @@ -0,0 +1,6 @@ +Scatter plot unfilled marker edgecolor +-------------------------------------- + +For :meth:`~matplotlib.axes.Axes.scatter`, when both the `facecolor` +and `edgecolor` are specified for unfilled marker types, the `edgecolor` +is used. Previously, the points took on the `facecolor`. diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py index 40959b06fe64..b5a048b47ac8 100644 --- a/lib/matplotlib/axes/_axes.py +++ b/lib/matplotlib/axes/_axes.py @@ -4291,9 +4291,8 @@ def scatter(self, x, y, s=None, c=None, marker=None, cmap=None, norm=None, - 'none': No patch boundary will be drawn. - A color or sequence of colors. - For non-filled markers, *edgecolors* is ignored. Instead, the color - is determined like with 'face', i.e. from *c*, *colors*, or - *facecolors*. + For non-filled markers, *edgecolors* kwarg (if it is not None, + 'face' or 'none') dictates the color of the marker. plotnonfinite : bool, default: False Whether to plot points with nonfinite *c* (i.e. ``inf``, ``-inf`` @@ -4378,6 +4377,11 @@ def scatter(self, x, y, s=None, c=None, marker=None, cmap=None, norm=None, path = marker_obj.get_path().transformed( marker_obj.get_transform()) if not marker_obj.is_filled(): + # In classic mode or non-classic mode + if edgecolors is None or edgecolors == 'face': + edgecolors = colors + colors = 'none' + if linewidths is None: linewidths = rcParams['lines.linewidth'] elif np.iterable(linewidths): @@ -4389,8 +4393,8 @@ def scatter(self, x, y, s=None, c=None, marker=None, cmap=None, norm=None, collection = mcoll.PathCollection( (path,), scales, - facecolors=colors if marker_obj.is_filled() else 'none', - edgecolors=edgecolors if marker_obj.is_filled() else colors, + facecolors=colors, + edgecolors=edgecolors, linewidths=linewidths, offsets=offsets, transOffset=kwargs.pop('transform', self.transData), diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index 56f45518c340..079a5d9cc6c3 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -2367,6 +2367,21 @@ def get_next_color(): c, None, kwargs={}, xsize=2, get_next_color_func=get_next_color) +@pytest.mark.parametrize(('facecolor', 'edgecolor', 'expected_color'), [ + ('red', 'cyan', 'cyan'), + (None, 'cyan', 'cyan'), + ('red', None, 'red') +]) +def test_scatter_edgecolor(facecolor, edgecolor, expected_color): + fig, ax = plt.subplots() + artist = ax.scatter(x=[1, 2, 3], y=[1, 2, 3], s=550, + linewidth=5, marker='2', + facecolor=facecolor, + edgecolor=edgecolor) + result_color = artist.get_edgecolor()[0] + assert mcolors.to_hex(result_color) == mcolors.to_hex(expected_color) + + def test_as_mpl_axes_api(): # tests the _as_mpl_axes api from matplotlib.projections.polar import PolarAxes