Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
extras.py2267 linesDownload Raw Back to ma
1"""
2Masked arrays add-ons.
3
4A collection of utilities for `numpy.ma`.
5
6:author: Pierre Gerard-Marchant
7:contact: pierregm_at_uga_dot_edu
8
9"""
10__all__ = [
11    'apply_along_axis', 'apply_over_axes', 'atleast_1d', 'atleast_2d',
12    'atleast_3d', 'average', 'clump_masked', 'clump_unmasked', 'column_stack',
13    'compress_cols', 'compress_nd', 'compress_rowcols', 'compress_rows',
14    'count_masked', 'corrcoef', 'cov', 'diagflat', 'dot', 'dstack', 'ediff1d',
15    'flatnotmasked_contiguous', 'flatnotmasked_edges', 'hsplit', 'hstack',
16    'isin', 'in1d', 'intersect1d', 'mask_cols', 'mask_rowcols', 'mask_rows',
17    'masked_all', 'masked_all_like', 'median', 'mr_', 'ndenumerate',
18    'notmasked_contiguous', 'notmasked_edges', 'polyfit', 'row_stack',
19    'setdiff1d', 'setxor1d', 'stack', 'unique', 'union1d', 'vander', 'vstack',
20    ]
21
22import functools
23import itertools
24import warnings
25
26import numpy as np
27from numpy import array as nxarray, ndarray
28from numpy.lib._function_base_impl import _ureduce
29from numpy.lib._index_tricks_impl import AxisConcatenator
30from numpy.lib.array_utils import normalize_axis_index, normalize_axis_tuple
31
32from . import core as ma
33from .core import (  # noqa: F401
34    MAError,
35    MaskedArray,
36    add,
37    array,
38    asarray,
39    concatenate,
40    count,
41    dot,
42    filled,
43    get_masked_subclass,
44    getdata,
45    getmask,
46    getmaskarray,
47    make_mask_descr,
48    mask_or,
49    masked,
50    masked_array,
51    nomask,
52    ones,
53    sort,
54    zeros,
55)
56
57
58def issequence(seq):
59    """
60    Is seq a sequence (ndarray, list or tuple)?
61
62    """
63    return isinstance(seq, (ndarray, tuple, list))
64
65
66def count_masked(arr, axis=None):
67    """
68    Count the number of masked elements along the given axis.
69
70    Parameters
71    ----------
72    arr : array_like
73        An array with (possibly) masked elements.
74    axis : int, optional
75        Axis along which to count. If None (default), a flattened
76        version of the array is used.
77
78    Returns
79    -------
80    count : int, ndarray
81        The total number of masked elements (axis=None) or the number
82        of masked elements along each slice of the given axis.
83
84    See Also
85    --------
86    MaskedArray.count : Count non-masked elements.
87
88    Examples
89    --------
90    >>> import numpy as np
91    >>> a = np.arange(9).reshape((3,3))
92    >>> a = np.ma.array(a)
93    >>> a[1, 0] = np.ma.masked
94    >>> a[1, 2] = np.ma.masked
95    >>> a[2, 1] = np.ma.masked
96    >>> a
97    masked_array(
98      data=[[0, 1, 2],
99            [--, 4, --],
100            [6, --, 8]],
101      mask=[[False, False, False],
102            [ True, False,  True],
103            [False,  True, False]],
104      fill_value=999999)
105    >>> np.ma.count_masked(a)
106    3
107
108    When the `axis` keyword is used an array is returned.
109
110    >>> np.ma.count_masked(a, axis=0)
111    array([1, 1, 1])
112    >>> np.ma.count_masked(a, axis=1)
113    array([0, 2, 1])
114
115    """
116    m = getmaskarray(arr)
117    return m.sum(axis)
118
119
120def masked_all(shape, dtype=float):
121    """
122    Empty masked array with all elements masked.
123
124    Return an empty masked array of the given shape and dtype, where all the
125    data are masked.
126
127    Parameters
128    ----------
129    shape : int or tuple of ints
130        Shape of the required MaskedArray, e.g., ``(2, 3)`` or ``2``.
131    dtype : dtype, optional
132        Data type of the output.
133
134    Returns
135    -------
136    a : MaskedArray
137        A masked array with all data masked.
138
139    See Also
140    --------
141    masked_all_like : Empty masked array modelled on an existing array.
142
143    Notes
144    -----
145    Unlike other masked array creation functions (e.g. `numpy.ma.zeros`,
146    `numpy.ma.ones`, `numpy.ma.full`), `masked_all` does not initialize the
147    values of the array, and may therefore be marginally faster. However,
148    the values stored in the newly allocated array are arbitrary. For
149    reproducible behavior, be sure to set each element of the array before
150    reading.
151
152    Examples
153    --------
154    >>> import numpy as np
155    >>> np.ma.masked_all((3, 3))
156    masked_array(
157      data=[[--, --, --],
158            [--, --, --],
159            [--, --, --]],
160      mask=[[ True,  True,  True],
161            [ True,  True,  True],
162            [ True,  True,  True]],
163      fill_value=1e+20,
164      dtype=float64)
165
166    The `dtype` parameter defines the underlying data type.
167
168    >>> a = np.ma.masked_all((3, 3))
169    >>> a.dtype
170    dtype('float64')
171    >>> a = np.ma.masked_all((3, 3), dtype=np.int32)
172    >>> a.dtype
173    dtype('int32')
174
175    """
176    a = masked_array(np.empty(shape, dtype),
177                     mask=np.ones(shape, make_mask_descr(dtype)))
178    return a
179
180
181def masked_all_like(arr):
182    """
183    Empty masked array with the properties of an existing array.
184
185    Return an empty masked array of the same shape and dtype as
186    the array `arr`, where all the data are masked.
187
188    Parameters
189    ----------
190    arr : ndarray
191        An array describing the shape and dtype of the required MaskedArray.
192
193    Returns
194    -------
195    a : MaskedArray
196        A masked array with all data masked.
197
198    Raises
199    ------
200    AttributeError
201        If `arr` doesn't have a shape attribute (i.e. not an ndarray)
202
203    See Also
204    --------
205    masked_all : Empty masked array with all elements masked.
206
207    Notes
208    -----
209    Unlike other masked array creation functions (e.g. `numpy.ma.zeros_like`,
210    `numpy.ma.ones_like`, `numpy.ma.full_like`), `masked_all_like` does not
211    initialize the values of the array, and may therefore be marginally
212    faster. However, the values stored in the newly allocated array are
213    arbitrary. For reproducible behavior, be sure to set each element of the
214    array before reading.
215
216    Examples
217    --------
218    >>> import numpy as np
219    >>> arr = np.zeros((2, 3), dtype=np.float32)
220    >>> arr
221    array([[0., 0., 0.],
222           [0., 0., 0.]], dtype=float32)
223    >>> np.ma.masked_all_like(arr)
224    masked_array(
225      data=[[--, --, --],
226            [--, --, --]],
227      mask=[[ True,  True,  True],
228            [ True,  True,  True]],
229      fill_value=np.float64(1e+20),
230      dtype=float32)
231
232    The dtype of the masked array matches the dtype of `arr`.
233
234    >>> arr.dtype
235    dtype('float32')
236    >>> np.ma.masked_all_like(arr).dtype
237    dtype('float32')
238
239    """
240    a = np.empty_like(arr).view(MaskedArray)
241    a._mask = np.ones(a.shape, dtype=make_mask_descr(a.dtype))
242    return a
243
244
245#####--------------------------------------------------------------------------
246#---- --- Standard functions ---
247#####--------------------------------------------------------------------------
248
249def _fromnxfunction_function(_fromnxfunction):
250    """
251    Decorator to wrap a "_fromnxfunction" function, wrapping a numpy function as a
252    masked array function, with proper docstring and name.
253
254    Parameters
255    ----------
256    _fromnxfunction : ({params}) -> ndarray, {params}) -> masked_array
257        Wrapper function that calls the wrapped numpy function
258
259    Returns
260    -------
261    decorator : (f: ({params}) -> ndarray) -> ({params}) -> masked_array
262        Function that accepts a numpy function and returns a masked array function
263
264    """
265    def decorator(npfunc, /):
266        def wrapper(*args, **kwargs):
267            return _fromnxfunction(npfunc, *args, **kwargs)
268
269        functools.update_wrapper(wrapper, npfunc, assigned=("__name__", "__qualname__"))
270        wrapper.__doc__ = ma.doc_note(
271            npfunc.__doc__,
272            "The function is applied to both the ``_data`` and the ``_mask``, if any.",
273        )
274        return wrapper
275
276    return decorator
277
278
279@_fromnxfunction_function
280def _fromnxfunction_single(npfunc, a, /, *args, **kwargs):
281    """
282    Wraps a NumPy function that can be called with a single array argument followed by
283    auxiliary args that are passed verbatim for both the data and mask calls.
284    """
285    return masked_array(
286        data=npfunc(np.asarray(a), *args, **kwargs),
287        mask=npfunc(getmaskarray(a), *args, **kwargs),
288    )
289
290
291@_fromnxfunction_function
292def _fromnxfunction_seq(npfunc, arys, /, *args, **kwargs):
293    """
294    Wraps a NumPy function that can be called with a single sequence of arrays followed
295    by auxiliary args that are passed verbatim for both the data and mask calls.
296    """
297    return masked_array(
298        data=npfunc(tuple(np.asarray(a) for a in arys), *args, **kwargs),
299        mask=npfunc(tuple(getmaskarray(a) for a in arys), *args, **kwargs),
300    )
301
302@_fromnxfunction_function
303def _fromnxfunction_allargs(npfunc, /, *arys, **kwargs):
304    """
305    Wraps a NumPy function that can be called with multiple array arguments.
306    All args are converted to arrays even if they are not so already.
307    This makes it possible to process scalars as 1-D arrays.
308    Only keyword arguments are passed through verbatim for the data and mask calls.
309    Arrays arguments are processed independently and the results are returned in a list.
310    If only one arg is present, the return value is just the processed array instead of
311    a list.
312    """
313    out = tuple(
314        masked_array(
315            data=npfunc(np.asarray(a), **kwargs),
316            mask=npfunc(getmaskarray(a), **kwargs),
317        )
318        for a in arys
319    )
320    return out[0] if len(out) == 1 else out
321
322
323atleast_1d = _fromnxfunction_allargs(np.atleast_1d)
324atleast_2d = _fromnxfunction_allargs(np.atleast_2d)
325atleast_3d = _fromnxfunction_allargs(np.atleast_3d)
326
327vstack = row_stack = _fromnxfunction_seq(np.vstack)
328hstack = _fromnxfunction_seq(np.hstack)
329column_stack = _fromnxfunction_seq(np.column_stack)
330dstack = _fromnxfunction_seq(np.dstack)
331stack = _fromnxfunction_seq(np.stack)
332
333hsplit = _fromnxfunction_single(np.hsplit)
334diagflat = _fromnxfunction_single(np.diagflat)
335
336
337#####--------------------------------------------------------------------------
338#----
339#####--------------------------------------------------------------------------
340def flatten_inplace(seq):
341    """Flatten a sequence in place."""
342    k = 0
343    while (k != len(seq)):
344        while hasattr(seq[k], '__iter__'):
345            seq[k:(k + 1)] = seq[k]
346        k += 1
347    return seq
348
349
350def apply_along_axis(func1d, axis, arr, *args, **kwargs):
351    """
352    (This docstring should be overwritten)
353    """
354    arr = array(arr, copy=False, subok=True)
355    nd = arr.ndim
356    axis = normalize_axis_index(axis, nd)
357    ind = [0] * (nd - 1)
358    i = np.zeros(nd, 'O')
359    indlist = list(range(nd))
360    indlist.remove(axis)
361    i[axis] = slice(None, None)
362    outshape = np.asarray(arr.shape).take(indlist)
363    i.put(indlist, ind)
364    res = func1d(arr[tuple(i.tolist())], *args, **kwargs)
365    #  if res is a number, then we have a smaller output array
366    asscalar = np.isscalar(res)
367    if not asscalar:
368        try:
369            len(res)
370        except TypeError:
371            asscalar = True
372    # Note: we shouldn't set the dtype of the output from the first result
373    # so we force the type to object, and build a list of dtypes.  We'll
374    # just take the largest, to avoid some downcasting
375    dtypes = []
376    if asscalar:
377        dtypes.append(np.asarray(res).dtype)
378        outarr = zeros(outshape, object)
379        outarr[tuple(ind)] = res
380        Ntot = np.prod(outshape)
381        k = 1
382        while k < Ntot:
383            # increment the index
384            ind[-1] += 1
385            n = -1
386            while (ind[n] >= outshape[n]) and (n > (1 - nd)):
387                ind[n - 1] += 1
388                ind[n] = 0
389                n -= 1
390            i.put(indlist, ind)
391            res = func1d(arr[tuple(i.tolist())], *args, **kwargs)
392            outarr[tuple(ind)] = res
393            dtypes.append(asarray(res).dtype)
394            k += 1
395    else:
396        res = array(res, copy=False, subok=True)
397        j = i.copy()
398        j[axis] = ([slice(None, None)] * res.ndim)
399        j.put(indlist, ind)
400        Ntot = np.prod(outshape)
401        holdshape = outshape
402        outshape = list(arr.shape)
403        outshape[axis] = res.shape
404        dtypes.append(asarray(res).dtype)
405        outshape = flatten_inplace(outshape)
406        outarr = zeros(outshape, object)
407        outarr[tuple(flatten_inplace(j.tolist()))] = res
408        k = 1
409        while k < Ntot:
410            # increment the index
411            ind[-1] += 1
412            n = -1
413            while (ind[n] >= holdshape[n]) and (n > (1 - nd)):
414                ind[n - 1] += 1
415                ind[n] = 0
416                n -= 1
417            i.put(indlist, ind)
418            j.put(indlist, ind)
419            res = func1d(arr[tuple(i.tolist())], *args, **kwargs)
420            outarr[tuple(flatten_inplace(j.tolist()))] = res
421            dtypes.append(asarray(res).dtype)
422            k += 1
423    max_dtypes = np.dtype(np.asarray(dtypes).max())
424    if not hasattr(arr, '_mask'):
425        result = np.asarray(outarr, dtype=max_dtypes)
426    else:
427        result = asarray(outarr, dtype=max_dtypes)
428        result.fill_value = ma.default_fill_value(result)
429    return result
430
431
432apply_along_axis.__doc__ = np.apply_along_axis.__doc__
433
434
435def apply_over_axes(func, a, axes):
436    """
437    (This docstring will be overwritten)
438    """
439    val = asarray(a)
440    N = a.ndim
441    if array(axes).ndim == 0:
442        axes = (axes,)
443    for axis in axes:
444        if axis < 0:
445            axis = N + axis
446        args = (val, axis)
447        res = func(*args)
448        if res.ndim == val.ndim:
449            val = res
450        else:
451            res = ma.expand_dims(res, axis)
452            if res.ndim == val.ndim:
453                val = res
454            else:
455                raise ValueError("function is not returning "
456                        "an array of the correct shape")
457    return val
458
459
460if apply_over_axes.__doc__ is not None:
461    apply_over_axes.__doc__ = np.apply_over_axes.__doc__[
462        :np.apply_over_axes.__doc__.find('Notes')].rstrip() + \
463    """
464
465    Examples
466    --------
467    >>> import numpy as np
468    >>> a = np.ma.arange(24).reshape(2,3,4)
469    >>> a[:,0,1] = np.ma.masked
470    >>> a[:,1,:] = np.ma.masked
471    >>> a
472    masked_array(
473      data=[[[0, --, 2, 3],
474             [--, --, --, --],
475             [8, 9, 10, 11]],
476            [[12, --, 14, 15],
477             [--, --, --, --],
478             [20, 21, 22, 23]]],
479      mask=[[[False,  True, False, False],
480             [ True,  True,  True,  True],
481             [False, False, False, False]],
482            [[False,  True, False, False],
483             [ True,  True,  True,  True],
484             [False, False, False, False]]],
485      fill_value=999999)
486    >>> np.ma.apply_over_axes(np.ma.sum, a, [0,2])
487    masked_array(
488      data=[[[46],
489             [--],
490             [124]]],
491      mask=[[[False],
492             [ True],
493             [False]]],
494      fill_value=999999)
495
496    Tuple axis arguments to ufuncs are equivalent:
497
498    >>> np.ma.sum(a, axis=(0,2)).reshape((1,-1,1))
499    masked_array(
500      data=[[[46],
501             [--],
502             [124]]],
503      mask=[[[False],
504             [ True],
505             [False]]],
506      fill_value=999999)
507    """
508
509
510def average(a, axis=None, weights=None, returned=False, *,
511            keepdims=np._NoValue):
512    """
513    Return the weighted average of array over the given axis.
514
515    Parameters
516    ----------
517    a : array_like
518        Data to be averaged.
519        Masked entries are not taken into account in the computation.
520    axis : None or int or tuple of ints, optional
521        Axis or axes along which to average `a`.  The default,
522        `axis=None`, will average over all of the elements of the input array.
523        If axis is a tuple of ints, averaging is performed on all of the axes
524        specified in the tuple instead of a single axis or all the axes as
525        before.
526    weights : array_like, optional
527        An array of weights associated with the values in `a`. Each value in
528        `a` contributes to the average according to its associated weight.
529        The array of weights must be the same shape as `a` if no axis is
530        specified, otherwise the weights must have dimensions and shape
531        consistent with `a` along the specified axis.
532        If `weights=None`, then all data in `a` are assumed to have a
533        weight equal to one.
534        The calculation is::
535
536            avg = sum(a * weights) / sum(weights)
537
538        where the sum is over all included elements.
539        The only constraint on the values of `weights` is that `sum(weights)`
540        must not be 0.
541    returned : bool, optional
542        Flag indicating whether a tuple ``(result, sum of weights)``
543        should be returned as output (True), or just the result (False).
544        Default is False.
545    keepdims : bool, optional
546        If this is set to True, the axes which are reduced are left
547        in the result as dimensions with size one. With this option,
548        the result will broadcast correctly against the original `a`.
549        *Note:* `keepdims` will not work with instances of `numpy.matrix`
550        or other classes whose methods do not support `keepdims`.
551
552        .. versionadded:: 1.23.0
553
554    Returns
555    -------
556    average, [sum_of_weights] : (tuple of) scalar or MaskedArray
557        The average along the specified axis. When returned is `True`,
558        return a tuple with the average as the first element and the sum
559        of the weights as the second element. The return type is `np.float64`
560        if `a` is of integer type and floats smaller than `float64`, or the
561        input data-type, otherwise. If returned, `sum_of_weights` is always
562        `float64`.
563
564    Raises
565    ------
566    ZeroDivisionError
567        When all weights along axis are zero. See `numpy.ma.average` for a
568        version robust to this type of error.
569    TypeError
570        When `weights` does not have the same shape as `a`, and `axis=None`.
571    ValueError
572        When `weights` does not have dimensions and shape consistent with `a`
573        along specified `axis`.
574
575    Examples
576    --------
577    >>> import numpy as np
578    >>> a = np.ma.array([1., 2., 3., 4.], mask=[False, False, True, True])
579    >>> np.ma.average(a, weights=[3, 1, 0, 0])
580    1.25
581
582    >>> x = np.ma.arange(6.).reshape(3, 2)
583    >>> x
584    masked_array(
585      data=[[0., 1.],
586            [2., 3.],
587            [4., 5.]],
588      mask=False,
589      fill_value=1e+20)
590    >>> data = np.arange(8).reshape((2, 2, 2))
591    >>> data
592    array([[[0, 1],
593            [2, 3]],
594           [[4, 5],
595            [6, 7]]])
596    >>> np.ma.average(data, axis=(0, 1), weights=[[1./4, 3./4], [1., 1./2]])
597    masked_array(data=[3.4, 4.4],
598             mask=[False, False],
599       fill_value=1e+20)
600    >>> np.ma.average(data, axis=0, weights=[[1./4, 3./4], [1., 1./2]])
601    Traceback (most recent call last):
602        ...
603    ValueError: Shape of weights must be consistent
604    with shape of a along specified axis.
605
606    >>> avg, sumweights = np.ma.average(x, axis=0, weights=[1, 2, 3],
607    ...                                 returned=True)
608    >>> avg
609    masked_array(data=[2.6666666666666665, 3.6666666666666665],
610                 mask=[False, False],
611           fill_value=1e+20)
612
613    With ``keepdims=True``, the following result has shape (3, 1).
614
615    >>> np.ma.average(x, axis=1, keepdims=True)
616    masked_array(
617      data=[[0.5],
618            [2.5],
619            [4.5]],
620      mask=False,
621      fill_value=1e+20)
622    """
623    a = asarray(a)
624    m = getmask(a)
625
626    if axis is not None:
627        axis = normalize_axis_tuple(axis, a.ndim, argname="axis")
628
629    if keepdims is np._NoValue:
630        # Don't pass on the keepdims argument if one wasn't given.
631        keepdims_kw = {}
632    else:
633        keepdims_kw = {'keepdims': keepdims}
634
635    if weights is None:
636        avg = a.mean(axis, **keepdims_kw)
637        scl = avg.dtype.type(a.count(axis))
638    else:
639        wgt = asarray(weights)
640
641        if issubclass(a.dtype.type, (np.integer, np.bool)):
642            result_dtype = np.result_type(a.dtype, wgt.dtype, 'f8')
643        else:
644            result_dtype = np.result_type(a.dtype, wgt.dtype)
645
646        # Sanity checks
647        if a.shape != wgt.shape:
648            if axis is None:
649                raise TypeError(
650                    "Axis must be specified when shapes of a and weights "
651                    "differ.")
652            if wgt.shape != tuple(a.shape[ax] for ax in axis):
653                raise ValueError(
654                    "Shape of weights must be consistent with "
655                    "shape of a along specified axis.")
656
657            # setup wgt to broadcast along axis
658            wgt = wgt.transpose(np.argsort(axis))
659            wgt = wgt.reshape(tuple((s if ax in axis else 1)
660                                    for ax, s in enumerate(a.shape)))
661
662        if m is not nomask:
663            wgt = wgt * (~a.mask)
664            wgt.mask |= a.mask
665
666        scl = wgt.sum(axis=axis, dtype=result_dtype, **keepdims_kw)
667        avg = np.multiply(a, wgt,
668                          dtype=result_dtype).sum(axis, **keepdims_kw) / scl
669
670    if returned:
671        if scl.shape != avg.shape:
672            scl = np.broadcast_to(scl, avg.shape).copy()
673        return avg, scl
674    else:
675        return avg
676
677
678def median(a, axis=None, out=None, overwrite_input=False, keepdims=False):
679    """
680    Compute the median along the specified axis.
681
682    Returns the median of the array elements.
683
684    Parameters
685    ----------
686    a : array_like
687        Input array or object that can be converted to an array.
688    axis : int, optional
689        Axis along which the medians are computed. The default (None) is
690        to compute the median along a flattened version of the array.
691    out : ndarray, optional
692        Alternative output array in which to place the result. It must
693        have the same shape and buffer length as the expected output
694        but the type will be cast if necessary.
695    overwrite_input : bool, optional
696        If True, then allow use of memory of input array (a) for
697        calculations. The input array will be modified by the call to
698        median. This will save memory when you do not need to preserve
699        the contents of the input array. Treat the input as undefined,
700        but it will probably be fully or partially sorted. Default is
701        False. Note that, if `overwrite_input` is True, and the input
702        is not already an `ndarray`, an error will be raised.
703    keepdims : bool, optional
704        If this is set to True, the axes which are reduced are left
705        in the result as dimensions with size one. With this option,
706        the result will broadcast correctly against the input array.
707
708    Returns
709    -------
710    median : ndarray
711        A new array holding the result is returned unless out is
712        specified, in which case a reference to out is returned.
713        Return data-type is `float64` for integers and floats smaller than
714        `float64`, or the input data-type, otherwise.
715
716    See Also
717    --------
718    mean
719
720    Notes
721    -----
722    Given a vector ``V`` with ``N`` non masked values, the median of ``V``
723    is the middle value of a sorted copy of ``V`` (``Vs``) - i.e.
724    ``Vs[(N-1)/2]``, when ``N`` is odd, or ``{Vs[N/2 - 1] + Vs[N/2]}/2``
725    when ``N`` is even.
726
727    Examples
728    --------
729    >>> import numpy as np
730    >>> x = np.ma.array(np.arange(8), mask=[0]*4 + [1]*4)
731    >>> np.ma.median(x)
732    1.5
733
734    >>> x = np.ma.array(np.arange(10).reshape(2, 5), mask=[0]*6 + [1]*4)
735    >>> np.ma.median(x)
736    2.5
737    >>> np.ma.median(x, axis=-1, overwrite_input=True)
738    masked_array(data=[2.0, 5.0],
739                 mask=[False, False],
740           fill_value=1e+20)
741
742    """
743    if not hasattr(a, 'mask'):
744        m = np.median(getdata(a, subok=True), axis=axis,
745                      out=out, overwrite_input=overwrite_input,
746                      keepdims=keepdims)
747        if isinstance(m, np.ndarray) and 1 <= m.ndim:
748            return masked_array(m, copy=False)
749        else:
750            return m
751
752    return _ureduce(a, func=_median, keepdims=keepdims, axis=axis, out=out,
753                    overwrite_input=overwrite_input)
754
755
756def _median(a, axis=None, out=None, overwrite_input=False):
757    # when an unmasked NaN is present return it, so we need to sort the NaN
758    # values behind the mask
759    if np.issubdtype(a.dtype, np.inexact):
760        fill_value = np.inf
761    else:
762        fill_value = None
763    if overwrite_input:
764        if axis is None:
765            asorted = a.ravel()
766            asorted.sort(fill_value=fill_value)
767        else:
768            a.sort(axis=axis, fill_value=fill_value)
769            asorted = a
770    else:
771        asorted = sort(a, axis=axis, fill_value=fill_value)
772
773    if axis is None:
774        axis = 0
775    else:
776        axis = normalize_axis_index(axis, asorted.ndim)
777
778    if asorted.shape[axis] == 0:
779        # for empty axis integer indices fail so use slicing to get same result
780        # as median (which is mean of empty slice = nan)
781        indexer = [slice(None)] * asorted.ndim
782        indexer[axis] = slice(0, 0)
783        indexer = tuple(indexer)
784        return np.ma.mean(asorted[indexer], axis=axis, out=out)
785
786    if asorted.ndim == 1:
787        idx, odd = divmod(count(asorted), 2)
788        mid = asorted[idx + odd - 1:idx + 1]
789        if np.issubdtype(asorted.dtype, np.inexact) and asorted.size > 0:
790            # avoid inf / x = masked
791            s = mid.sum(out=out)
792            if not odd:
793                s = np.true_divide(s, 2., casting='safe', out=out)
794            s = np.lib._utils_impl._median_nancheck(asorted, s, axis)
795        else:
796            s = mid.mean(out=out)
797
798        # if result is masked either the input contained enough
799        # minimum_fill_value so that it would be the median or all values
800        # masked
801        if np.ma.is_masked(s) and not np.all(asorted.mask):
802            return np.ma.minimum_fill_value(asorted)
803        return s
804
805    counts = count(asorted, axis=axis, keepdims=True)
806    h = counts // 2
807
808    # duplicate high if odd number of elements so mean does nothing
809    odd = counts % 2 == 1
810    l = np.where(odd, h, h - 1)
811
812    lh = np.concatenate([l, h], axis=axis)
813
814    # get low and high median
815    low_high = np.take_along_axis(asorted, lh, axis=axis)
816
817    def replace_masked(s):
818        # Replace masked entries with minimum_full_value unless it all values
819        # are masked. This is required as the sort order of values equal or
820        # larger than the fill value is undefined and a valid value placed
821        # elsewhere, e.g. [4, --, inf].
822        if np.ma.is_masked(s):
823            rep = (~np.all(asorted.mask, axis=axis, keepdims=True)) & s.mask
824            s.data[rep] = np.ma.minimum_fill_value(asorted)
825            s.mask[rep] = False
826
827    replace_masked(low_high)
828
829    if np.issubdtype(asorted.dtype, np.inexact):
830        # avoid inf / x = masked
831        s = np.ma.sum(low_high, axis=axis, out=out)
832        np.true_divide(s.data, 2., casting='unsafe', out=s.data)
833
834        s = np.lib._utils_impl._median_nancheck(asorted, s, axis)
835    else:
836        s = np.ma.mean(low_high, axis=axis, out=out)
837
838    return s
839
840
841def compress_nd(x, axis=None):
842    """Suppress slices from multiple dimensions which contain masked values.
843
844    Parameters
845    ----------
846    x : array_like, MaskedArray
847        The array to operate on. If not a MaskedArray instance (or if no array
848        elements are masked), `x` is interpreted as a MaskedArray with `mask`
849        set to `nomask`.
850    axis : tuple of ints or int, optional
851        Which dimensions to suppress slices from can be configured with this
852        parameter.
853        - If axis is a tuple of ints, those are the axes to suppress slices from.
854        - If axis is an int, then that is the only axis to suppress slices from.
855        - If axis is None, all axis are selected.
856
857    Returns
858    -------
859    compress_array : ndarray
860        The compressed array.
861
862    Examples
863    --------
864    >>> import numpy as np
865    >>> arr = [[1, 2], [3, 4]]
866    >>> mask = [[0, 1], [0, 0]]
867    >>> x = np.ma.array(arr, mask=mask)
868    >>> np.ma.compress_nd(x, axis=0)
869    array([[3, 4]])
870    >>> np.ma.compress_nd(x, axis=1)
871    array([[1],
872           [3]])
873    >>> np.ma.compress_nd(x)
874    array([[3]])
875
876    """
877    x = asarray(x)
878    m = getmask(x)
879    # Set axis to tuple of ints
880    if axis is None:
881        axis = tuple(range(x.ndim))
882    else:
883        axis = normalize_axis_tuple(axis, x.ndim)
884
885    # Nothing is masked: return x
886    if m is nomask or not m.any():
887        return x._data
888    # All is masked: return empty
889    if m.all():
890        return nxarray([])
891    # Filter elements through boolean indexing
892    data = x._data
893    for ax in axis:
894        axes = tuple(list(range(ax)) + list(range(ax + 1, x.ndim)))
895        data = data[(slice(None),) * ax + (~m.any(axis=axes),)]
896    return data
897
898
899def compress_rowcols(x, axis=None):
900    """
901    Suppress the rows and/or columns of a 2-D array that contain
902    masked values.
903
904    The suppression behavior is selected with the `axis` parameter.
905
906    - If axis is None, both rows and columns are suppressed.
907    - If axis is 0, only rows are suppressed.
908    - If axis is 1 or -1, only columns are suppressed.
909
910    Parameters
911    ----------
912    x : array_like, MaskedArray
913        The array to operate on.  If not a MaskedArray instance (or if no array
914        elements are masked), `x` is interpreted as a MaskedArray with
915        `mask` set to `nomask`. Must be a 2D array.
916    axis : int, optional
917        Axis along which to perform the operation. Default is None.
918
919    Returns
920    -------
921    compressed_array : ndarray
922        The compressed array.
923
924    Examples
925    --------
926    >>> import numpy as np
927    >>> x = np.ma.array(np.arange(9).reshape(3, 3), mask=[[1, 0, 0],
928    ...                                                   [1, 0, 0],
929    ...                                                   [0, 0, 0]])
930    >>> x
931    masked_array(
932      data=[[--, 1, 2],
933            [--, 4, 5],
934            [6, 7, 8]],
935      mask=[[ True, False, False],
936            [ True, False, False],
937            [False, False, False]],
938      fill_value=999999)
939
940    >>> np.ma.compress_rowcols(x)
941    array([[7, 8]])
942    >>> np.ma.compress_rowcols(x, 0)
943    array([[6, 7, 8]])
944    >>> np.ma.compress_rowcols(x, 1)
945    array([[1, 2],
946           [4, 5],
947           [7, 8]])
948
949    """
950    if asarray(x).ndim != 2:
951        raise NotImplementedError("compress_rowcols works for 2D arrays only.")
952    return compress_nd(x, axis=axis)
953
954
955def compress_rows(a):
956    """
957    Suppress whole rows of a 2-D array that contain masked values.
958
959    This is equivalent to ``np.ma.compress_rowcols(a, 0)``, see
960    `compress_rowcols` for details.
961
962    Parameters
963    ----------
964    x : array_like, MaskedArray
965        The array to operate on. If not a MaskedArray instance (or if no array
966        elements are masked), `x` is interpreted as a MaskedArray with
967        `mask` set to `nomask`. Must be a 2D array.
968
969    Returns
970    -------
971    compressed_array : ndarray
972        The compressed array.
973
974    See Also
975    --------
976    compress_rowcols
977
978    Examples
979    --------
980    >>> import numpy as np
981    >>> a = np.ma.array(np.arange(9).reshape(3, 3), mask=[[1, 0, 0],
982    ...                                                   [1, 0, 0],
983    ...                                                   [0, 0, 0]])
984    >>> np.ma.compress_rows(a)
985    array([[6, 7, 8]])
986
987    """
988    a = asarray(a)
989    if a.ndim != 2:
990        raise NotImplementedError("compress_rows works for 2D arrays only.")
991    return compress_rowcols(a, 0)
992
993
994def compress_cols(a):
995    """
996    Suppress whole columns of a 2-D array that contain masked values.
997
998    This is equivalent to ``np.ma.compress_rowcols(a, 1)``, see
999    `compress_rowcols` for details.
1000
1001    Parameters
1002    ----------
1003    x : array_like, MaskedArray
1004        The array to operate on.  If not a MaskedArray instance (or if no array
1005        elements are masked), `x` is interpreted as a MaskedArray with
1006        `mask` set to `nomask`. Must be a 2D array.
1007
1008    Returns
1009    -------
1010    compressed_array : ndarray
1011        The compressed array.
1012
1013    See Also
1014    --------
1015    compress_rowcols
1016
1017    Examples
1018    --------
1019    >>> import numpy as np
1020    >>> a = np.ma.array(np.arange(9).reshape(3, 3), mask=[[1, 0, 0],
1021    ...                                                   [1, 0, 0],
1022    ...                                                   [0, 0, 0]])
1023    >>> np.ma.compress_cols(a)
1024    array([[1, 2],
1025           [4, 5],
1026           [7, 8]])
1027
1028    """
1029    a = asarray(a)
1030    if a.ndim != 2:
1031        raise NotImplementedError("compress_cols works for 2D arrays only.")
1032    return compress_rowcols(a, 1)
1033
1034
1035def mask_rowcols(a, axis=None):
1036    """
1037    Mask rows and/or columns of a 2D array that contain masked values.
1038
1039    Mask whole rows and/or columns of a 2D array that contain
1040    masked values.  The masking behavior is selected using the
1041    `axis` parameter.
1042
1043      - If `axis` is None, rows *and* columns are masked.
1044      - If `axis` is 0, only rows are masked.
1045      - If `axis` is 1 or -1, only columns are masked.
1046
1047    Parameters
1048    ----------
1049    a : array_like, MaskedArray
1050        The array to mask.  If not a MaskedArray instance (or if no array
1051        elements are masked), the result is a MaskedArray with `mask` set
1052        to `nomask` (False). Must be a 2D array.
1053    axis : int, optional
1054        Axis along which to perform the operation. If None, applies to a
1055        flattened version of the array.
1056
1057    Returns
1058    -------
1059    a : MaskedArray
1060        A modified version of the input array, masked depending on the value
1061        of the `axis` parameter.
1062
1063    Raises
1064    ------
1065    NotImplementedError
1066        If input array `a` is not 2D.
1067
1068    See Also
1069    --------
1070    mask_rows : Mask rows of a 2D array that contain masked values.
1071    mask_cols : Mask cols of a 2D array that contain masked values.
1072    masked_where : Mask where a condition is met.
1073
1074    Notes
1075    -----
1076    The input array's mask is modified by this function.
1077
1078    Examples
1079    --------
1080    >>> import numpy as np
1081    >>> a = np.zeros((3, 3), dtype=int)
1082    >>> a[1, 1] = 1
1083    >>> a
1084    array([[0, 0, 0],
1085           [0, 1, 0],
1086           [0, 0, 0]])
1087    >>> a = np.ma.masked_equal(a, 1)
1088    >>> a
1089    masked_array(
1090      data=[[0, 0, 0],
1091            [0, --, 0],
1092            [0, 0, 0]],
1093      mask=[[False, False, False],
1094            [False,  True, False],
1095            [False, False, False]],
1096      fill_value=1)
1097    >>> np.ma.mask_rowcols(a)
1098    masked_array(
1099      data=[[0, --, 0],
1100            [--, --, --],
1101            [0, --, 0]],
1102      mask=[[False,  True, False],
1103            [ True,  True,  True],
1104            [False,  True, False]],
1105      fill_value=1)
1106
1107    """
1108    a = array(a, subok=False)
1109    if a.ndim != 2:
1110        raise NotImplementedError("mask_rowcols works for 2D arrays only.")
1111    m = getmask(a)
1112    # Nothing is masked: return a
1113    if m is nomask or not m.any():
1114        return a
1115    maskedval = m.nonzero()
1116    a._mask = a._mask.copy()
1117    if not axis:
1118        a[np.unique(maskedval[0])] = masked
1119    if axis in [None, 1, -1]:
1120        a[:, np.unique(maskedval[1])] = masked
1121    return a
1122
1123
1124def mask_rows(a, axis=np._NoValue):
1125    """
1126    Mask rows of a 2D array that contain masked values.
1127
1128    This function is a shortcut to ``mask_rowcols`` with `axis` equal to 0.
1129
1130    See Also
1131    --------
1132    mask_rowcols : Mask rows and/or columns of a 2D array.
1133    masked_where : Mask where a condition is met.
1134
1135    Examples
1136    --------
1137    >>> import numpy as np
1138    >>> a = np.zeros((3, 3), dtype=int)
1139    >>> a[1, 1] = 1
1140    >>> a
1141    array([[0, 0, 0],
1142           [0, 1, 0],
1143           [0, 0, 0]])
1144    >>> a = np.ma.masked_equal(a, 1)
1145    >>> a
1146    masked_array(
1147      data=[[0, 0, 0],
1148            [0, --, 0],
1149            [0, 0, 0]],
1150      mask=[[False, False, False],
1151            [False,  True, False],
1152            [False, False, False]],
1153      fill_value=1)
1154
1155    >>> np.ma.mask_rows(a)
1156    masked_array(
1157      data=[[0, 0, 0],
1158            [--, --, --],
1159            [0, 0, 0]],
1160      mask=[[False, False, False],
1161            [ True,  True,  True],
1162            [False, False, False]],
1163      fill_value=1)
1164
1165    """
1166    if axis is not np._NoValue:
1167        # remove the axis argument when this deprecation expires
1168        # NumPy 1.18.0, 2019-11-28
1169        warnings.warn(
1170            "The axis argument has always been ignored, in future passing it "
1171            "will raise TypeError", DeprecationWarning, stacklevel=2)
1172    return mask_rowcols(a, 0)
1173
1174
1175def mask_cols(a, axis=np._NoValue):
1176    """
1177    Mask columns of a 2D array that contain masked values.
1178
1179    This function is a shortcut to ``mask_rowcols`` with `axis` equal to 1.
1180
1181    See Also
1182    --------
1183    mask_rowcols : Mask rows and/or columns of a 2D array.
1184    masked_where : Mask where a condition is met.
1185
1186    Examples
1187    --------
1188    >>> import numpy as np
1189    >>> a = np.zeros((3, 3), dtype=int)
1190    >>> a[1, 1] = 1
1191    >>> a
1192    array([[0, 0, 0],
1193           [0, 1, 0],
1194           [0, 0, 0]])
1195    >>> a = np.ma.masked_equal(a, 1)
1196    >>> a
1197    masked_array(
1198      data=[[0, 0, 0],
1199            [0, --, 0],
1200            [0, 0, 0]],

Showing the first 1,200 of 2267 lines. Download the file for the rest.

codekingpro/portable-devtools · Team Ai