diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py index f1c5e2c97c3e..c89e5cba8bf6 100644 --- a/lib/matplotlib/axes/_axes.py +++ b/lib/matplotlib/axes/_axes.py @@ -4212,19 +4212,26 @@ def invalid_shape_exception(csize, xsize): except ValueError: pass # Failed to convert to float array; must be color specs. else: + # handle the documented special case of a 2D array with 1 + # row which as RGB(A) to broadcast. + if c.shape == (1, 4) or c.shape == (1, 3): + c_is_mapped = False + if c.size != xsize: + valid_shape = False # If c can be either mapped values or a RGB(A) color, prefer # the former if shapes match, the latter otherwise. - if c.size == xsize: + elif c.size == xsize: c = c.ravel() c_is_mapped = True else: # Wrong size; it must not be intended for mapping. if c.shape in ((3,), (4,)): _log.warning( - "'c' argument looks like a single numeric RGB or " + "*c* argument looks like a single numeric RGB or " "RGBA sequence, which should be avoided as value-" "mapping will have precedence in case its length " - "matches with 'x' & 'y'. Please use a 2-D array " - "with a single row if you really want to specify " + "matches with *x* & *y*. Please use the *color* " + "keyword-argument or provide a 2-D array " + "with a single row if you intend to specify " "the same RGB or RGBA value for all points.") valid_shape = False if not c_is_mapped: @@ -4268,14 +4275,14 @@ def scatter(self, x, y, s=None, c=None, marker=None, cmap=None, norm=None, The marker size in points**2. Default is ``rcParams['lines.markersize'] ** 2``. - c : color, sequence, or sequence of colors, optional - The marker color. Possible values: + c : array-like or list of colors or color, optional + The marker colors. Possible values: - - A single color format string. - - A sequence of colors of length n. - A scalar or sequence of n numbers to be mapped to colors using *cmap* and *norm*. - A 2-D array in which the rows are RGB or RGBA. + - A sequence of colors of length n. + - A single color format string. Note that *c* should not be a single numeric RGB or RGBA sequence because that is indistinguishable from an array of values to be @@ -4284,9 +4291,12 @@ def scatter(self, x, y, s=None, c=None, marker=None, cmap=None, norm=None, matching will have precedence in case of a size matching with *x* and *y*. - Defaults to ``None``. In that case the marker color is determined - by the value of ``color``, ``facecolor`` or ``facecolors``. In case - those are not specified or ``None``, the marker color is determined + If you wish to specify a single color for all points + prefer the *color* keyword argument. + + Defaults to `None`. In that case the marker color is determined + by the value of *color*, *facecolor* or *facecolors*. In case + those are not specified or `None`, the marker color is determined by the next color of the ``Axes``' current "shape and fill" color cycle. This cycle defaults to :rc:`axes.prop_cycle`. diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index 3ec602f84c4d..69b460a7e5f0 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -2088,6 +2088,22 @@ def get_next_color(): c=c_case, edgecolors="black", kwargs={}, xsize=xsize, get_next_color_func=get_next_color) + @pytest.mark.style('default') + @check_figures_equal(extensions=["png"]) + def test_scatter_single_color_c(self, fig_test, fig_ref): + rgb = [[1, 0.5, 0.05]] + rgba = [[1, 0.5, 0.05, .5]] + + # set via color kwarg + ax_ref = fig_ref.subplots() + ax_ref.scatter(np.ones(3), range(3), color=rgb) + ax_ref.scatter(np.ones(4)*2, range(4), color=rgba) + + # set via broadcasting via c + ax_test = fig_test.subplots() + ax_test.scatter(np.ones(3), range(3), c=rgb) + ax_test.scatter(np.ones(4)*2, range(4), c=rgba) + def _params(c=None, xsize=2, **kwargs): edgecolors = kwargs.pop('edgecolors', None)