diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py index f2d5fbc7f95a..1eb12b4ca919 100644 --- a/lib/matplotlib/axes/_axes.py +++ b/lib/matplotlib/axes/_axes.py @@ -3778,7 +3778,7 @@ def boxplot(self, x, notch=None, sym=None, vert=None, whis=None, stats['med'] = med if conf_intervals is not None: - if np.shape(conf_intervals)[0] != len(bxpstats): + if len(conf_intervals) != len(bxpstats): raise ValueError( "'conf_intervals' and 'x' have different lengths") else: @@ -6555,8 +6555,6 @@ def hist(self, x, bins=None, range=None, density=False, weights=None, if histtype == 'barstacked' and not stacked: stacked = True - # basic input validation - input_empty = np.size(x) == 0 # Massage 'x' for processing. x = cbook._reshape_2D(x, 'x') nx = len(x) # number of datasets @@ -6581,9 +6579,13 @@ def hist(self, x, bins=None, range=None, density=False, weights=None, if len(w) != nx: raise ValueError('weights should have the same shape as x') + input_empty = True for xi, wi in zip(x, w): - if wi is not None and len(wi) != len(xi): + len_xi = len(xi) + if wi is not None and len(wi) != len_xi: raise ValueError('weights should have the same shape as x') + if len_xi: + input_empty = False if color is None: color = [self._get_lines.get_next_color() for i in range(nx)] diff --git a/lib/matplotlib/cbook/__init__.py b/lib/matplotlib/cbook/__init__.py index 6209d15643f2..a15b023301b4 100644 --- a/lib/matplotlib/cbook/__init__.py +++ b/lib/matplotlib/cbook/__init__.py @@ -989,7 +989,12 @@ def _combine_masks(*args): else: if isinstance(x, np.ma.MaskedArray) and x.ndim > 1: raise ValueError("Masked arrays must be 1-D") - x = np.asanyarray(x) + try: + x = np.asanyarray(x) + except (np.VisibleDeprecationWarning, ValueError): + # NumPy 1.19 raises a warning about ragged arrays, but we want + # to accept basically anything here. + x = np.asanyarray(x, dtype=object) if x.ndim == 1: x = safe_masked_invalid(x) seqlist[i] = True @@ -1316,24 +1321,48 @@ def _reshape_2D(X, name): Use Fortran ordering to convert ndarrays and lists of iterables to lists of 1D arrays. - Lists of iterables are converted by applying `np.asarray` to each of their - elements. 1D ndarrays are returned in a singleton list containing them. - 2D ndarrays are converted to the list of their *columns*. + Lists of iterables are converted by applying `np.asanyarray` to each of + their elements. 1D ndarrays are returned in a singleton list containing + them. 2D ndarrays are converted to the list of their *columns*. *name* is used to generate the error message for invalid inputs. """ - # Iterate over columns for ndarrays, over rows otherwise. - X = np.atleast_1d(X.T if isinstance(X, np.ndarray) else np.asarray(X)) + # Iterate over columns for ndarrays. + if isinstance(X, np.ndarray): + X = X.T + + if len(X) == 0: + return [[]] + elif X.ndim == 1 and np.ndim(X[0]) == 0: + # 1D array of scalars: directly return it. + return [X] + elif X.ndim in [1, 2]: + # 2D array, or 1D array of iterables: flatten them first. + return [np.reshape(x, -1) for x in X] + else: + raise ValueError(f'{name} must have 2 or fewer dimensions') + + # Iterate over list of iterables. if len(X) == 0: return [[]] - elif X.ndim == 1 and np.ndim(X[0]) == 0: + + result = [] + is_1d = True + for xi in X: + xi = np.asanyarray(xi) + nd = np.ndim(xi) + if nd > 1: + raise ValueError(f'{name} must have 2 or fewer dimensions') + elif nd == 1 and len(xi) != 1: + is_1d = False + result.append(xi.reshape(-1)) + + if is_1d: # 1D array of scalars: directly return it. - return [X] - elif X.ndim in [1, 2]: - # 2D array, or 1D array of iterables: flatten them first. - return [np.reshape(x, -1) for x in X] + return [np.reshape(result, -1)] else: - raise ValueError("{} must have 2 or fewer dimensions".format(name)) + # 2D array, or 1D array of iterables: use flattened version. + return result def violin_stats(X, method, points=100, quantiles=None): @@ -1399,10 +1428,10 @@ def violin_stats(X, method, points=100, quantiles=None): quantiles = _reshape_2D(quantiles, "quantiles") # Else, mock quantiles if is none or empty else: - quantiles = [[]] * np.shape(X)[0] + quantiles = [[]] * len(X) # quantiles should has the same size as dataset - if np.shape(X)[:1] != np.shape(quantiles)[:1]: + if len(X) != len(quantiles): raise ValueError("List of violinplot statistics and quantiles values" " must have the same length") @@ -1577,8 +1606,15 @@ def index_of(y): try: return y.index.values, y.values except AttributeError: + pass + try: y = _check_1d(y) + except (np.VisibleDeprecationWarning, ValueError): + # NumPy 1.19 will warn on ragged input, and we can't actually use it. + pass + else: return np.arange(y.shape[0], dtype=float), y + raise ValueError('Input could not be cast to an at-least-1D NumPy array') def safe_first_element(obj): diff --git a/lib/matplotlib/tests/test_backend_svg.py b/lib/matplotlib/tests/test_backend_svg.py index 7bdc3ca33b0a..14d1805f3ffd 100644 --- a/lib/matplotlib/tests/test_backend_svg.py +++ b/lib/matplotlib/tests/test_backend_svg.py @@ -191,7 +191,8 @@ def include(gid, obj): elif obj.axes is None: return False if isinstance(obj, plt.Line2D): - if np.array(obj.get_data()).shape == (2, 1): + xdata, ydata = obj.get_data() + if len(xdata) == len(ydata) == 1: return False elif not hasattr(obj, "axes") or obj.axes is None: return False diff --git a/lib/mpl_toolkits/mplot3d/art3d.py b/lib/mpl_toolkits/mplot3d/art3d.py index 9309371b8476..5ea30204db64 100644 --- a/lib/mpl_toolkits/mplot3d/art3d.py +++ b/lib/mpl_toolkits/mplot3d/art3d.py @@ -257,7 +257,7 @@ def set_segments(self, segments): """ Set 3D segments. """ - self._segments3d = np.asanyarray(segments) + self._segments3d = segments LineCollection.set_segments(self, []) def do_3d_projection(self, renderer):