Repository: dask/dask
File: dask/array/routines.py (Python)

Code before:

    if m.ndim > 2:
        raise ValueError("m has more than 2 dimensions")
    if y is not None and y.ndim > 2:
        raise ValueError("y has more than 2 dimensions")

    X = array(m, ndmin=2, dtype=dtype)

    if ddof is None:
        ddof = 1 if bias == 0 else 0

    if not rowvar and m.ndim != 1:
        X = X.T
    if X.shape[0] == 0:
        return array([]).reshape(0, 0)
    if y is not None:
        y = array(y, ndmin=2, dtype=dtype)
        if not rowvar and y.shape[0] != 1:
            y = y.T
        X = concatenate((X, y), axis=0)

    # Get the product of frequencies and weights
    w = None
    if fweights is not None:
        fweights = asarray(fweights, dtype=float)
        if not (fweights == around(fweights)).all():
            raise TypeError("fweights must be integer")
        if fweights.ndim > 1:
            raise RuntimeError("cannot handle multidimensional fweights")
        if fweights.shape[0] != X.shape[1]:
            raise RuntimeError("incompatible numbers of samples and fweights")
        if (fweights < 0).any():
            raise ValueError("fweights cannot be negative")
        w = fweights
    if aweights is not None:
        aweights = asarray(aweights, dtype=float)
        if aweights.ndim > 1:
            raise RuntimeError("cannot handle multidimensional aweights")
        if aweights.shape[0] != X.shape[1]:
            raise RuntimeError("incompatible numbers of samples and aweights")
        if any(aweights < 0):
            raise ValueError("aweights cannot be negative")
        if w is None:
            w = aweights
        else:
            w *= aweights

    avg, w_sum = average(X, axis=1, weights=w, returned=True)
    w_sum = w_sum[0]

    # Determine the normalization

Review comment (performance):
Can `fweights` be a large (potentially distribute) array? If so, this round and `.all` might be expensive.

I'd recommend moving this check if it might cause problems.

Code after:

    if m.ndim > 2:
        raise ValueError("m has more than 2 dimensions")
    if y is not None and y.ndim > 2:
        raise ValueError("y has more than 2 dimensions")

    X = array(m, ndmin=2, dtype=dtype)

    if ddof is None:
        ddof = 1 if bias == 0 else 0

    if not rowvar and m.ndim != 1:
        X = X.T
    if X.shape[0] == 0:
        return array([]).reshape(0, 0)
    if y is not None:
        y = array(y, ndmin=2, dtype=dtype)
        if not rowvar and y.shape[0] != 1:
            y = y.T
        X = concatenate((X, y), axis=0)

    # Unlike NumPy, these checks don't include:
    #    - if fweights are all integers
    #    - if either fweights or aweights are all non-negative
    # These checks potientially expensive for distributed arrays.
    w = None
    if fweights is not None:
        fweights = asarray(fweights, dtype=float)
        if fweights.ndim > 1:
            raise RuntimeError("cannot handle multidimensional fweights")
        if fweights.shape[0] != X.shape[1]:
            raise RuntimeError("incompatible numbers of samples and fweights")
        w = fweights
    if aweights is not None:
        aweights = asarray(aweights, dtype=float)
        if aweights.ndim > 1:
            raise RuntimeError("cannot handle multidimensional aweights")
        if aweights.shape[0] != X.shape[1]:
            raise RuntimeError("incompatible numbers of samples and aweights")
        if w is None:
            w = aweights
        else:
            w *= aweights

    avg, w_sum = average(X, axis=1, weights=w, returned=True)
    w_sum = w_sum[0]

    # Determine the normalization
    if w is None:
        fact = X.shape[1] - ddof
    elif ddof == 0: