Skip to content

Commit 86e5e65

Browse files
committed
Merge pull request #4123 from efiring/scattercleanup
MNT/DOC/API : clean up docs and kwarg handling in scatter
2 parents ed79638 + f200421 commit 86e5e65

File tree

5 files changed

+101
-43
lines changed

5 files changed

+101
-43
lines changed

doc/api/api_changes/code_removal.rst

+8
Original file line numberDiff line numberDiff line change
@@ -85,3 +85,11 @@ mpl.py
8585

8686
Remove the module `matplotlib.mpl`. Deprecated in 1.3 by
8787
PR #1670 and commit 78ce67d161625833cacff23cfe5d74920248c5b2
88+
89+
90+
Remove ``faceted`` kwarg from scatter
91+
-------------------------------------
92+
93+
Remove support for the ``faceted`` kwarg. This was deprecated in
94+
d48b34288e9651ff95c3b8a071ef5ac5cf50bae7 (2008-04-18!) and replaced by
95+
``edgecolor``.

lib/matplotlib/axes/_axes.py

+68-36
Original file line numberDiff line numberDiff line change
@@ -3509,9 +3509,10 @@ def dopatch(xs, ys, **kwargs):
35093509
medians=medians, fliers=fliers, means=means)
35103510

35113511
@docstring.dedent_interpd
3512-
def scatter(self, x, y, s=20, c='b', marker='o', cmap=None, norm=None,
3512+
def scatter(self, x, y, s=20, c=None, marker='o', cmap=None, norm=None,
35133513
vmin=None, vmax=None, alpha=None, linewidths=None,
3514-
verts=None, **kwargs):
3514+
verts=None, edgecolors=None,
3515+
**kwargs):
35153516
"""
35163517
Make a scatter plot of x vs y, where x and y are sequence like objects
35173518
of the same lengths.
@@ -3531,11 +3532,14 @@ def scatter(self, x, y, s=20, c='b', marker='o', cmap=None, norm=None,
35313532
(see below). Note that `c` should not be a single numeric RGB or
35323533
RGBA sequence because that is indistinguishable from an array of
35333534
values to be colormapped. `c` can be a 2-D array in which the
3534-
rows are RGB or RGBA, however.
3535+
rows are RGB or RGBA, however, including the case of a single
3536+
row to specify the same color for all points.
35353537
35363538
marker : `~matplotlib.markers.MarkerStyle`, optional, default: 'o'
35373539
See `~matplotlib.markers` for more information on the different
3538-
styles of markers scatter supports.
3540+
styles of markers scatter supports. `marker` can be either
3541+
an instance of the class or the text shorthand for a particular
3542+
marker.
35393543
35403544
cmap : `~matplotlib.colors.Colormap`, optional, default: None
35413545
A `~matplotlib.colors.Colormap` instance or registered name.
@@ -3557,10 +3561,14 @@ def scatter(self, x, y, s=20, c='b', marker='o', cmap=None, norm=None,
35573561
The alpha blending value, between 0 (transparent) and 1 (opaque)
35583562
35593563
linewidths : scalar or array_like, optional, default: None
3560-
If None, defaults to (lines.linewidth,). Note that this is a
3561-
tuple, and if you set the linewidths argument you must set it as a
3562-
sequence of floats, as required by
3563-
`~matplotlib.collections.RegularPolyCollection`.
3564+
If None, defaults to (lines.linewidth,).
3565+
3566+
edgecolors : color or sequence of color, optional, default: None
3567+
If None, defaults to (patch.edgecolor).
3568+
If 'face', the edge color will always be the same as
3569+
the face color. If it is 'none', the patch boundary will not
3570+
be drawn. For non-filled markers, the `edgecolors` kwarg
3571+
is ignored; color is determined by `c`.
35643572
35653573
Returns
35663574
-------
@@ -3585,6 +3593,32 @@ def scatter(self, x, y, s=20, c='b', marker='o', cmap=None, norm=None,
35853593
if not self._hold:
35863594
self.cla()
35873595

3596+
# Process **kwargs to handle aliases, conflicts with explicit kwargs:
3597+
3598+
facecolors = None
3599+
ec = kwargs.pop('edgecolor', None)
3600+
if ec is not None:
3601+
edgecolors = ec
3602+
fc = kwargs.pop('facecolor', None)
3603+
if fc is not None:
3604+
facecolors = fc
3605+
fc = kwargs.pop('facecolors', None)
3606+
if fc is not None:
3607+
facecolors = fc
3608+
# 'color' should be deprecated in scatter, or clearly defined;
3609+
# since it isn't, I am giving it low priority.
3610+
co = kwargs.pop('color', None)
3611+
if co is not None:
3612+
if edgecolors is None:
3613+
edgecolors = co
3614+
if facecolors is None:
3615+
facecolors = co
3616+
if c is None:
3617+
if facecolors is not None:
3618+
c = facecolors
3619+
else:
3620+
c = 'b' # the original default
3621+
35883622
self._process_unit_info(xdata=x, ydata=y, kwargs=kwargs)
35893623
x = self.convert_xunits(x)
35903624
y = self.convert_yunits(y)
@@ -3598,43 +3632,41 @@ def scatter(self, x, y, s=20, c='b', marker='o', cmap=None, norm=None,
35983632

35993633
s = np.ma.ravel(s) # This doesn't have to match x, y in size.
36003634

3601-
c_is_stringy = is_string_like(c) or is_sequence_of_strings(c)
3602-
if not c_is_stringy:
3603-
c = np.asanyarray(c)
3604-
if c.size == x.size:
3605-
c = np.ma.ravel(c)
3635+
# After this block, c_array will be None unless
3636+
# c is an array for mapping. The potential ambiguity
3637+
# with a sequence of 3 or 4 numbers is resolved in
3638+
# favor mapping, not rgb or rgba.
3639+
try:
3640+
c_array = np.asanyarray(c, dtype=float)
3641+
if c_array.shape == x.shape:
3642+
c = np.ma.ravel(c_array)
3643+
else:
3644+
# Wrong shape; it must not be intended for mapping.
3645+
c_array = None
3646+
except ValueError:
3647+
# Failed to make a floating-point array; c must be color specs.
3648+
c_array = None
3649+
3650+
if c_array is None:
3651+
colors = c # must be acceptable as PathCollection facecolors
3652+
else:
3653+
colors = None # use cmap, norm after collection is created
36063654

3655+
# c will be unchanged unless it is the same length as x:
36073656
x, y, s, c = cbook.delete_masked_points(x, y, s, c)
36083657

36093658
scales = s # Renamed for readability below.
36103659

3611-
if c_is_stringy:
3612-
colors = mcolors.colorConverter.to_rgba_array(c, alpha)
3613-
else:
3614-
# The inherent ambiguity is resolved in favor of color
3615-
# mapping, not interpretation as rgb or rgba:
3616-
if c.size == x.size:
3617-
colors = None # use cmap, norm after collection is created
3618-
else:
3619-
colors = mcolors.colorConverter.to_rgba_array(c, alpha)
3620-
3621-
faceted = kwargs.pop('faceted', None)
3622-
edgecolors = kwargs.get('edgecolors', None)
3623-
if faceted is not None:
3624-
cbook.warn_deprecated(
3625-
'1.2', name='faceted', alternative='edgecolor',
3626-
obj_type='option')
3627-
if faceted:
3628-
edgecolors = None
3629-
else:
3630-
edgecolors = 'none'
3631-
36323660
# to be API compatible
36333661
if marker is None and not (verts is None):
36343662
marker = (verts, 0)
36353663
verts = None
36363664

3637-
marker_obj = mmarkers.MarkerStyle(marker)
3665+
if isinstance(marker, mmarkers.MarkerStyle):
3666+
marker_obj = marker
3667+
else:
3668+
marker_obj = mmarkers.MarkerStyle(marker)
3669+
36383670
path = marker_obj.get_path().transformed(
36393671
marker_obj.get_transform())
36403672
if not marker_obj.is_filled():
@@ -3649,9 +3681,9 @@ def scatter(self, x, y, s=20, c='b', marker='o', cmap=None, norm=None,
36493681
linewidths=linewidths,
36503682
offsets=offsets,
36513683
transOffset=kwargs.pop('transform', self.transData),
3684+
alpha=alpha
36523685
)
36533686
collection.set_transform(mtransforms.IdentityTransform())
3654-
collection.set_alpha(alpha)
36553687
collection.update(kwargs)
36563688

36573689
if colors is None:

lib/matplotlib/collections.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -559,13 +559,13 @@ def set_color(self, c):
559559
def set_facecolor(self, c):
560560
"""
561561
Set the facecolor(s) of the collection. *c* can be a
562-
matplotlib color arg (all patches have same color), or a
563-
sequence of rgba tuples; if it is a sequence the patches will
562+
matplotlib color spec (all patches have same color), or a
563+
sequence of specs; if it is a sequence the patches will
564564
cycle through the sequence.
565565
566566
If *c* is 'none', the patch will not be filled.
567567
568-
ACCEPTS: matplotlib color arg or sequence of rgba tuples
568+
ACCEPTS: matplotlib color spec or sequence of specs
569569
"""
570570
self._is_filled = True
571571
try:
@@ -596,15 +596,15 @@ def get_edgecolor(self):
596596
def set_edgecolor(self, c):
597597
"""
598598
Set the edgecolor(s) of the collection. *c* can be a
599-
matplotlib color arg (all patches have same color), or a
600-
sequence of rgba tuples; if it is a sequence the patches will
599+
matplotlib color spec (all patches have same color), or a
600+
sequence of specs; if it is a sequence the patches will
601601
cycle through the sequence.
602602
603603
If *c* is 'face', the edge color will always be the same as
604604
the face color. If it is 'none', the patch boundary will not
605605
be drawn.
606606
607-
ACCEPTS: matplotlib color arg or sequence of rgba tuples
607+
ACCEPTS: matplotlib color spec or sequence of specs
608608
"""
609609
self._is_stroked = True
610610
try:

lib/matplotlib/tests/test_axes.py

+19-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import matplotlib
1717
from matplotlib.testing.decorators import image_comparison, cleanup
1818
import matplotlib.pyplot as plt
19+
import matplotlib.markers as mmarkers
1920
from numpy.testing import assert_array_equal
2021
import warnings
2122

@@ -1091,7 +1092,24 @@ def test_hist2d_transpose():
10911092
@image_comparison(baseline_images=['scatter'])
10921093
def test_scatter_plot():
10931094
ax = plt.axes()
1094-
ax.scatter([3, 4, 2, 6], [2, 5, 2, 3], c=['r', 'y', 'b', 'lime'], s=[24, 15, 19, 29])
1095+
ax.scatter([3, 4, 2, 6], [2, 5, 2, 3],
1096+
c=['r', 'y', 'b', 'lime'], s=[24, 15, 19, 29])
1097+
1098+
1099+
@image_comparison(baseline_images=['scatter_marker'], remove_text=True,
1100+
extensions=['png'])
1101+
def test_scatter_marker():
1102+
fig, (ax0, ax1) = plt.subplots(ncols=2)
1103+
ax0.scatter([3, 4, 2, 6], [2, 5, 2, 3],
1104+
c=[(1, 0, 0), 'y', 'b', 'lime'],
1105+
s=[60, 50, 40, 30],
1106+
edgecolors=['k', 'r', 'g', 'b'],
1107+
marker='s')
1108+
ax1.scatter([3, 4, 2, 6], [2, 5, 2, 3],
1109+
c=[(1, 0, 0), 'y', 'b', 'lime'],
1110+
s=[60, 50, 40, 30],
1111+
edgecolors=['k', 'r', 'g', 'b'],
1112+
marker=mmarkers.MarkerStyle('o', fillstyle='top'))
10951113

10961114

10971115
@cleanup

0 commit comments

Comments
 (0)