Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 5bb1449

Browse files
authored
Merge pull request #21884 from tacaswell/fix_errorbar_units
FIX: be more careful about coercing unit-full containers to ndarray
2 parents e9cbd9d + d52c2e8 commit 5bb1449

File tree

1 file changed

+48
-2
lines changed

1 file changed

+48
-2
lines changed

lib/matplotlib/axes/_axes.py

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3282,10 +3282,56 @@ def errorbar(self, x, y, yerr=None, xerr=None,
32823282
x = np.asarray(x, dtype=object)
32833283
if not isinstance(y, np.ndarray):
32843284
y = np.asarray(y, dtype=object)
3285+
3286+
def _upcast_err(err):
3287+
"""
3288+
Safely handle tuple of containers that carry units.
3289+
3290+
If the units are carried on the values then casting to object
3291+
arrays preserves the units, but if the units are on the containers
3292+
this will not work.
3293+
3294+
This function covers the case where the input to the xerr/yerr is a
3295+
length 2 tuple of equal length ndarray-subclasses that carry the
3296+
unit information in the container.
3297+
3298+
We defer coercing the units to be consistent to the underlying unit
3299+
library (and implicitly the broadcasting).
3300+
3301+
If we do not have a tuple of nested numpy array (subclasses),
3302+
fallback to casting to an object array.
3303+
3304+
"""
3305+
3306+
# we are here because we the container is not a numpy array, but it
3307+
# _is_ iterable (likely a list or a tuple but maybe something more
3308+
# exotic)
3309+
3310+
if (
3311+
# make sure it is not a scalar
3312+
np.iterable(err) and
3313+
# and it is not empty
3314+
len(err) > 0 and
3315+
# and the first element is an array sub-class use
3316+
# safe_first_element because getitem is index-first not
3317+
# location first on pandas objects so err[0] almost always
3318+
# fails.
3319+
isinstance(cbook.safe_first_element(err), np.ndarray)
3320+
):
3321+
# grab the type of the first element, we will try to promote
3322+
# the outer container to match the inner container
3323+
atype = type(cbook.safe_first_element(err))
3324+
# you can not directly pass data to the init of `np.ndarray`
3325+
if atype is np.ndarray:
3326+
return np.asarray(err, dtype=object)
3327+
# but you can for unyt and astropy uints
3328+
return atype(err)
3329+
return np.asarray(err, dtype=object)
3330+
32853331
if xerr is not None and not isinstance(xerr, np.ndarray):
3286-
xerr = np.asarray(xerr, dtype=object)
3332+
xerr = _upcast_err(xerr)
32873333
if yerr is not None and not isinstance(yerr, np.ndarray):
3288-
yerr = np.asarray(yerr, dtype=object)
3334+
yerr = _upcast_err(yerr)
32893335
x, y = np.atleast_1d(x, y) # Make sure all the args are iterable.
32903336
if len(x) != len(y):
32913337
raise ValueError("'x' and 'y' must have the same size")

0 commit comments

Comments
 (0)