Path: blob/master/ invest-robot-contest_TinkoffBotTwitch-main/venv/lib/python3.8/site-packages/numpy/ma/extras.py
7763 views
"""1Masked arrays add-ons.23A collection of utilities for `numpy.ma`.45:author: Pierre Gerard-Marchant6:contact: pierregm_at_uga_dot_edu7:version: $Id: extras.py 3473 2007-10-29 15:18:13Z jarrod.millman $89"""10__all__ = [11'apply_along_axis', 'apply_over_axes', 'atleast_1d', 'atleast_2d',12'atleast_3d', 'average', 'clump_masked', 'clump_unmasked',13'column_stack', 'compress_cols', 'compress_nd', 'compress_rowcols',14'compress_rows', 'count_masked', 'corrcoef', 'cov', 'diagflat', 'dot',15'dstack', 'ediff1d', 'flatnotmasked_contiguous', 'flatnotmasked_edges',16'hsplit', 'hstack', 'isin', 'in1d', 'intersect1d', 'mask_cols', 'mask_rowcols',17'mask_rows', 'masked_all', 'masked_all_like', 'median', 'mr_',18'notmasked_contiguous', 'notmasked_edges', 'polyfit', 'row_stack',19'setdiff1d', 'setxor1d', 'stack', 'unique', 'union1d', 'vander', 'vstack',20]2122import itertools23import warnings2425from . import core as ma26from .core import (27MaskedArray, MAError, add, array, asarray, concatenate, filled, count,28getmask, getmaskarray, make_mask_descr, masked, masked_array, mask_or,29nomask, ones, sort, zeros, getdata, get_masked_subclass, dot,30mask_rowcols31)3233import numpy as np34from numpy import ndarray, array as nxarray35from numpy.core.multiarray import normalize_axis_index36from numpy.core.numeric import normalize_axis_tuple37from numpy.lib.function_base import _ureduce38from numpy.lib.index_tricks import AxisConcatenator394041def issequence(seq):42"""43Is seq a sequence (ndarray, list or tuple)?4445"""46return isinstance(seq, (ndarray, tuple, list))474849def count_masked(arr, axis=None):50"""51Count the number of masked elements along the given axis.5253Parameters54----------55arr : array_like56An array with (possibly) masked elements.57axis : int, optional58Axis along which to count. If None (default), a flattened59version of the array is used.6061Returns62-------63count : int, ndarray64The total number of masked elements (axis=None) or the number65of masked elements along each slice of the given axis.6667See Also68--------69MaskedArray.count : Count non-masked elements.7071Examples72--------73>>> import numpy.ma as ma74>>> a = np.arange(9).reshape((3,3))75>>> a = ma.array(a)76>>> a[1, 0] = ma.masked77>>> a[1, 2] = ma.masked78>>> a[2, 1] = ma.masked79>>> a80masked_array(81data=[[0, 1, 2],82[--, 4, --],83[6, --, 8]],84mask=[[False, False, False],85[ True, False, True],86[False, True, False]],87fill_value=999999)88>>> ma.count_masked(a)8939091When the `axis` keyword is used an array is returned.9293>>> ma.count_masked(a, axis=0)94array([1, 1, 1])95>>> ma.count_masked(a, axis=1)96array([0, 2, 1])9798"""99m = getmaskarray(arr)100return m.sum(axis)101102103def masked_all(shape, dtype=float):104"""105Empty masked array with all elements masked.106107Return an empty masked array of the given shape and dtype, where all the108data are masked.109110Parameters111----------112shape : tuple113Shape of the required MaskedArray.114dtype : dtype, optional115Data type of the output.116117Returns118-------119a : MaskedArray120A masked array with all data masked.121122See Also123--------124masked_all_like : Empty masked array modelled on an existing array.125126Examples127--------128>>> import numpy.ma as ma129>>> ma.masked_all((3, 3))130masked_array(131data=[[--, --, --],132[--, --, --],133[--, --, --]],134mask=[[ True, True, True],135[ True, True, True],136[ True, True, True]],137fill_value=1e+20,138dtype=float64)139140The `dtype` parameter defines the underlying data type.141142>>> a = ma.masked_all((3, 3))143>>> a.dtype144dtype('float64')145>>> a = ma.masked_all((3, 3), dtype=np.int32)146>>> a.dtype147dtype('int32')148149"""150a = masked_array(np.empty(shape, dtype),151mask=np.ones(shape, make_mask_descr(dtype)))152return a153154155def masked_all_like(arr):156"""157Empty masked array with the properties of an existing array.158159Return an empty masked array of the same shape and dtype as160the array `arr`, where all the data are masked.161162Parameters163----------164arr : ndarray165An array describing the shape and dtype of the required MaskedArray.166167Returns168-------169a : MaskedArray170A masked array with all data masked.171172Raises173------174AttributeError175If `arr` doesn't have a shape attribute (i.e. not an ndarray)176177See Also178--------179masked_all : Empty masked array with all elements masked.180181Examples182--------183>>> import numpy.ma as ma184>>> arr = np.zeros((2, 3), dtype=np.float32)185>>> arr186array([[0., 0., 0.],187[0., 0., 0.]], dtype=float32)188>>> ma.masked_all_like(arr)189masked_array(190data=[[--, --, --],191[--, --, --]],192mask=[[ True, True, True],193[ True, True, True]],194fill_value=1e+20,195dtype=float32)196197The dtype of the masked array matches the dtype of `arr`.198199>>> arr.dtype200dtype('float32')201>>> ma.masked_all_like(arr).dtype202dtype('float32')203204"""205a = np.empty_like(arr).view(MaskedArray)206a._mask = np.ones(a.shape, dtype=make_mask_descr(a.dtype))207return a208209210#####--------------------------------------------------------------------------211#---- --- Standard functions ---212#####--------------------------------------------------------------------------213class _fromnxfunction:214"""215Defines a wrapper to adapt NumPy functions to masked arrays.216217218An instance of `_fromnxfunction` can be called with the same parameters219as the wrapped NumPy function. The docstring of `newfunc` is adapted from220the wrapped function as well, see `getdoc`.221222This class should not be used directly. Instead, one of its extensions that223provides support for a specific type of input should be used.224225Parameters226----------227funcname : str228The name of the function to be adapted. The function should be229in the NumPy namespace (i.e. ``np.funcname``).230231"""232233def __init__(self, funcname):234self.__name__ = funcname235self.__doc__ = self.getdoc()236237def getdoc(self):238"""239Retrieve the docstring and signature from the function.240241The ``__doc__`` attribute of the function is used as the docstring for242the new masked array version of the function. A note on application243of the function to the mask is appended.244245Parameters246----------247None248249"""250npfunc = getattr(np, self.__name__, None)251doc = getattr(npfunc, '__doc__', None)252if doc:253sig = self.__name__ + ma.get_object_signature(npfunc)254doc = ma.doc_note(doc, "The function is applied to both the _data "255"and the _mask, if any.")256return '\n\n'.join((sig, doc))257return258259def __call__(self, *args, **params):260pass261262263class _fromnxfunction_single(_fromnxfunction):264"""265A version of `_fromnxfunction` that is called with a single array266argument followed by auxiliary args that are passed verbatim for267both the data and mask calls.268"""269def __call__(self, x, *args, **params):270func = getattr(np, self.__name__)271if isinstance(x, ndarray):272_d = func(x.__array__(), *args, **params)273_m = func(getmaskarray(x), *args, **params)274return masked_array(_d, mask=_m)275else:276_d = func(np.asarray(x), *args, **params)277_m = func(getmaskarray(x), *args, **params)278return masked_array(_d, mask=_m)279280281class _fromnxfunction_seq(_fromnxfunction):282"""283A version of `_fromnxfunction` that is called with a single sequence284of arrays followed by auxiliary args that are passed verbatim for285both the data and mask calls.286"""287def __call__(self, x, *args, **params):288func = getattr(np, self.__name__)289_d = func(tuple([np.asarray(a) for a in x]), *args, **params)290_m = func(tuple([getmaskarray(a) for a in x]), *args, **params)291return masked_array(_d, mask=_m)292293294class _fromnxfunction_args(_fromnxfunction):295"""296A version of `_fromnxfunction` that is called with multiple array297arguments. The first non-array-like input marks the beginning of the298arguments that are passed verbatim for both the data and mask calls.299Array arguments are processed independently and the results are300returned in a list. If only one array is found, the return value is301just the processed array instead of a list.302"""303def __call__(self, *args, **params):304func = getattr(np, self.__name__)305arrays = []306args = list(args)307while len(args) > 0 and issequence(args[0]):308arrays.append(args.pop(0))309res = []310for x in arrays:311_d = func(np.asarray(x), *args, **params)312_m = func(getmaskarray(x), *args, **params)313res.append(masked_array(_d, mask=_m))314if len(arrays) == 1:315return res[0]316return res317318319class _fromnxfunction_allargs(_fromnxfunction):320"""321A version of `_fromnxfunction` that is called with multiple array322arguments. Similar to `_fromnxfunction_args` except that all args323are converted to arrays even if they are not so already. This makes324it possible to process scalars as 1-D arrays. Only keyword arguments325are passed through verbatim for the data and mask calls. Arrays326arguments are processed independently and the results are returned327in a list. If only one arg is present, the return value is just the328processed array instead of a list.329"""330def __call__(self, *args, **params):331func = getattr(np, self.__name__)332res = []333for x in args:334_d = func(np.asarray(x), **params)335_m = func(getmaskarray(x), **params)336res.append(masked_array(_d, mask=_m))337if len(args) == 1:338return res[0]339return res340341342atleast_1d = _fromnxfunction_allargs('atleast_1d')343atleast_2d = _fromnxfunction_allargs('atleast_2d')344atleast_3d = _fromnxfunction_allargs('atleast_3d')345346vstack = row_stack = _fromnxfunction_seq('vstack')347hstack = _fromnxfunction_seq('hstack')348column_stack = _fromnxfunction_seq('column_stack')349dstack = _fromnxfunction_seq('dstack')350stack = _fromnxfunction_seq('stack')351352hsplit = _fromnxfunction_single('hsplit')353354diagflat = _fromnxfunction_single('diagflat')355356357#####--------------------------------------------------------------------------358#----359#####--------------------------------------------------------------------------360def flatten_inplace(seq):361"""Flatten a sequence in place."""362k = 0363while (k != len(seq)):364while hasattr(seq[k], '__iter__'):365seq[k:(k + 1)] = seq[k]366k += 1367return seq368369370def apply_along_axis(func1d, axis, arr, *args, **kwargs):371"""372(This docstring should be overwritten)373"""374arr = array(arr, copy=False, subok=True)375nd = arr.ndim376axis = normalize_axis_index(axis, nd)377ind = [0] * (nd - 1)378i = np.zeros(nd, 'O')379indlist = list(range(nd))380indlist.remove(axis)381i[axis] = slice(None, None)382outshape = np.asarray(arr.shape).take(indlist)383i.put(indlist, ind)384res = func1d(arr[tuple(i.tolist())], *args, **kwargs)385# if res is a number, then we have a smaller output array386asscalar = np.isscalar(res)387if not asscalar:388try:389len(res)390except TypeError:391asscalar = True392# Note: we shouldn't set the dtype of the output from the first result393# so we force the type to object, and build a list of dtypes. We'll394# just take the largest, to avoid some downcasting395dtypes = []396if asscalar:397dtypes.append(np.asarray(res).dtype)398outarr = zeros(outshape, object)399outarr[tuple(ind)] = res400Ntot = np.product(outshape)401k = 1402while k < Ntot:403# increment the index404ind[-1] += 1405n = -1406while (ind[n] >= outshape[n]) and (n > (1 - nd)):407ind[n - 1] += 1408ind[n] = 0409n -= 1410i.put(indlist, ind)411res = func1d(arr[tuple(i.tolist())], *args, **kwargs)412outarr[tuple(ind)] = res413dtypes.append(asarray(res).dtype)414k += 1415else:416res = array(res, copy=False, subok=True)417j = i.copy()418j[axis] = ([slice(None, None)] * res.ndim)419j.put(indlist, ind)420Ntot = np.product(outshape)421holdshape = outshape422outshape = list(arr.shape)423outshape[axis] = res.shape424dtypes.append(asarray(res).dtype)425outshape = flatten_inplace(outshape)426outarr = zeros(outshape, object)427outarr[tuple(flatten_inplace(j.tolist()))] = res428k = 1429while k < Ntot:430# increment the index431ind[-1] += 1432n = -1433while (ind[n] >= holdshape[n]) and (n > (1 - nd)):434ind[n - 1] += 1435ind[n] = 0436n -= 1437i.put(indlist, ind)438j.put(indlist, ind)439res = func1d(arr[tuple(i.tolist())], *args, **kwargs)440outarr[tuple(flatten_inplace(j.tolist()))] = res441dtypes.append(asarray(res).dtype)442k += 1443max_dtypes = np.dtype(np.asarray(dtypes).max())444if not hasattr(arr, '_mask'):445result = np.asarray(outarr, dtype=max_dtypes)446else:447result = asarray(outarr, dtype=max_dtypes)448result.fill_value = ma.default_fill_value(result)449return result450apply_along_axis.__doc__ = np.apply_along_axis.__doc__451452453def apply_over_axes(func, a, axes):454"""455(This docstring will be overwritten)456"""457val = asarray(a)458N = a.ndim459if array(axes).ndim == 0:460axes = (axes,)461for axis in axes:462if axis < 0:463axis = N + axis464args = (val, axis)465res = func(*args)466if res.ndim == val.ndim:467val = res468else:469res = ma.expand_dims(res, axis)470if res.ndim == val.ndim:471val = res472else:473raise ValueError("function is not returning "474"an array of the correct shape")475return val476477if apply_over_axes.__doc__ is not None:478apply_over_axes.__doc__ = np.apply_over_axes.__doc__[479:np.apply_over_axes.__doc__.find('Notes')].rstrip() + \480"""481482Examples483--------484>>> a = np.ma.arange(24).reshape(2,3,4)485>>> a[:,0,1] = np.ma.masked486>>> a[:,1,:] = np.ma.masked487>>> a488masked_array(489data=[[[0, --, 2, 3],490[--, --, --, --],491[8, 9, 10, 11]],492[[12, --, 14, 15],493[--, --, --, --],494[20, 21, 22, 23]]],495mask=[[[False, True, False, False],496[ True, True, True, True],497[False, False, False, False]],498[[False, True, False, False],499[ True, True, True, True],500[False, False, False, False]]],501fill_value=999999)502>>> np.ma.apply_over_axes(np.ma.sum, a, [0,2])503masked_array(504data=[[[46],505[--],506[124]]],507mask=[[[False],508[ True],509[False]]],510fill_value=999999)511512Tuple axis arguments to ufuncs are equivalent:513514>>> np.ma.sum(a, axis=(0,2)).reshape((1,-1,1))515masked_array(516data=[[[46],517[--],518[124]]],519mask=[[[False],520[ True],521[False]]],522fill_value=999999)523"""524525526def average(a, axis=None, weights=None, returned=False):527"""528Return the weighted average of array over the given axis.529530Parameters531----------532a : array_like533Data to be averaged.534Masked entries are not taken into account in the computation.535axis : int, optional536Axis along which to average `a`. If None, averaging is done over537the flattened array.538weights : array_like, optional539The importance that each element has in the computation of the average.540The weights array can either be 1-D (in which case its length must be541the size of `a` along the given axis) or of the same shape as `a`.542If ``weights=None``, then all data in `a` are assumed to have a543weight equal to one. The 1-D calculation is::544545avg = sum(a * weights) / sum(weights)546547The only constraint on `weights` is that `sum(weights)` must not be 0.548returned : bool, optional549Flag indicating whether a tuple ``(result, sum of weights)``550should be returned as output (True), or just the result (False).551Default is False.552553Returns554-------555average, [sum_of_weights] : (tuple of) scalar or MaskedArray556The average along the specified axis. When returned is `True`,557return a tuple with the average as the first element and the sum558of the weights as the second element. The return type is `np.float64`559if `a` is of integer type and floats smaller than `float64`, or the560input data-type, otherwise. If returned, `sum_of_weights` is always561`float64`.562563Examples564--------565>>> a = np.ma.array([1., 2., 3., 4.], mask=[False, False, True, True])566>>> np.ma.average(a, weights=[3, 1, 0, 0])5671.25568569>>> x = np.ma.arange(6.).reshape(3, 2)570>>> x571masked_array(572data=[[0., 1.],573[2., 3.],574[4., 5.]],575mask=False,576fill_value=1e+20)577>>> avg, sumweights = np.ma.average(x, axis=0, weights=[1, 2, 3],578... returned=True)579>>> avg580masked_array(data=[2.6666666666666665, 3.6666666666666665],581mask=[False, False],582fill_value=1e+20)583584"""585a = asarray(a)586m = getmask(a)587588# inspired by 'average' in numpy/lib/function_base.py589590if weights is None:591avg = a.mean(axis)592scl = avg.dtype.type(a.count(axis))593else:594wgt = np.asanyarray(weights)595596if issubclass(a.dtype.type, (np.integer, np.bool_)):597result_dtype = np.result_type(a.dtype, wgt.dtype, 'f8')598else:599result_dtype = np.result_type(a.dtype, wgt.dtype)600601# Sanity checks602if a.shape != wgt.shape:603if axis is None:604raise TypeError(605"Axis must be specified when shapes of a and weights "606"differ.")607if wgt.ndim != 1:608raise TypeError(609"1D weights expected when shapes of a and weights differ.")610if wgt.shape[0] != a.shape[axis]:611raise ValueError(612"Length of weights not compatible with specified axis.")613614# setup wgt to broadcast along axis615wgt = np.broadcast_to(wgt, (a.ndim-1)*(1,) + wgt.shape, subok=True)616wgt = wgt.swapaxes(-1, axis)617618if m is not nomask:619wgt = wgt*(~a.mask)620621scl = wgt.sum(axis=axis, dtype=result_dtype)622avg = np.multiply(a, wgt, dtype=result_dtype).sum(axis)/scl623624if returned:625if scl.shape != avg.shape:626scl = np.broadcast_to(scl, avg.shape).copy()627return avg, scl628else:629return avg630631632def median(a, axis=None, out=None, overwrite_input=False, keepdims=False):633"""634Compute the median along the specified axis.635636Returns the median of the array elements.637638Parameters639----------640a : array_like641Input array or object that can be converted to an array.642axis : int, optional643Axis along which the medians are computed. The default (None) is644to compute the median along a flattened version of the array.645out : ndarray, optional646Alternative output array in which to place the result. It must647have the same shape and buffer length as the expected output648but the type will be cast if necessary.649overwrite_input : bool, optional650If True, then allow use of memory of input array (a) for651calculations. The input array will be modified by the call to652median. This will save memory when you do not need to preserve653the contents of the input array. Treat the input as undefined,654but it will probably be fully or partially sorted. Default is655False. Note that, if `overwrite_input` is True, and the input656is not already an `ndarray`, an error will be raised.657keepdims : bool, optional658If this is set to True, the axes which are reduced are left659in the result as dimensions with size one. With this option,660the result will broadcast correctly against the input array.661662.. versionadded:: 1.10.0663664Returns665-------666median : ndarray667A new array holding the result is returned unless out is668specified, in which case a reference to out is returned.669Return data-type is `float64` for integers and floats smaller than670`float64`, or the input data-type, otherwise.671672See Also673--------674mean675676Notes677-----678Given a vector ``V`` with ``N`` non masked values, the median of ``V``679is the middle value of a sorted copy of ``V`` (``Vs``) - i.e.680``Vs[(N-1)/2]``, when ``N`` is odd, or ``{Vs[N/2 - 1] + Vs[N/2]}/2``681when ``N`` is even.682683Examples684--------685>>> x = np.ma.array(np.arange(8), mask=[0]*4 + [1]*4)686>>> np.ma.median(x)6871.5688689>>> x = np.ma.array(np.arange(10).reshape(2, 5), mask=[0]*6 + [1]*4)690>>> np.ma.median(x)6912.5692>>> np.ma.median(x, axis=-1, overwrite_input=True)693masked_array(data=[2.0, 5.0],694mask=[False, False],695fill_value=1e+20)696697"""698if not hasattr(a, 'mask'):699m = np.median(getdata(a, subok=True), axis=axis,700out=out, overwrite_input=overwrite_input,701keepdims=keepdims)702if isinstance(m, np.ndarray) and 1 <= m.ndim:703return masked_array(m, copy=False)704else:705return m706707r, k = _ureduce(a, func=_median, axis=axis, out=out,708overwrite_input=overwrite_input)709if keepdims:710return r.reshape(k)711else:712return r713714def _median(a, axis=None, out=None, overwrite_input=False):715# when an unmasked NaN is present return it, so we need to sort the NaN716# values behind the mask717if np.issubdtype(a.dtype, np.inexact):718fill_value = np.inf719else:720fill_value = None721if overwrite_input:722if axis is None:723asorted = a.ravel()724asorted.sort(fill_value=fill_value)725else:726a.sort(axis=axis, fill_value=fill_value)727asorted = a728else:729asorted = sort(a, axis=axis, fill_value=fill_value)730731if axis is None:732axis = 0733else:734axis = normalize_axis_index(axis, asorted.ndim)735736if asorted.shape[axis] == 0:737# for empty axis integer indices fail so use slicing to get same result738# as median (which is mean of empty slice = nan)739indexer = [slice(None)] * asorted.ndim740indexer[axis] = slice(0, 0)741indexer = tuple(indexer)742return np.ma.mean(asorted[indexer], axis=axis, out=out)743744if asorted.ndim == 1:745idx, odd = divmod(count(asorted), 2)746mid = asorted[idx + odd - 1:idx + 1]747if np.issubdtype(asorted.dtype, np.inexact) and asorted.size > 0:748# avoid inf / x = masked749s = mid.sum(out=out)750if not odd:751s = np.true_divide(s, 2., casting='safe', out=out)752s = np.lib.utils._median_nancheck(asorted, s, axis)753else:754s = mid.mean(out=out)755756# if result is masked either the input contained enough757# minimum_fill_value so that it would be the median or all values758# masked759if np.ma.is_masked(s) and not np.all(asorted.mask):760return np.ma.minimum_fill_value(asorted)761return s762763counts = count(asorted, axis=axis, keepdims=True)764h = counts // 2765766# duplicate high if odd number of elements so mean does nothing767odd = counts % 2 == 1768l = np.where(odd, h, h-1)769770lh = np.concatenate([l,h], axis=axis)771772# get low and high median773low_high = np.take_along_axis(asorted, lh, axis=axis)774775def replace_masked(s):776# Replace masked entries with minimum_full_value unless it all values777# are masked. This is required as the sort order of values equal or778# larger than the fill value is undefined and a valid value placed779# elsewhere, e.g. [4, --, inf].780if np.ma.is_masked(s):781rep = (~np.all(asorted.mask, axis=axis, keepdims=True)) & s.mask782s.data[rep] = np.ma.minimum_fill_value(asorted)783s.mask[rep] = False784785replace_masked(low_high)786787if np.issubdtype(asorted.dtype, np.inexact):788# avoid inf / x = masked789s = np.ma.sum(low_high, axis=axis, out=out)790np.true_divide(s.data, 2., casting='unsafe', out=s.data)791792s = np.lib.utils._median_nancheck(asorted, s, axis)793else:794s = np.ma.mean(low_high, axis=axis, out=out)795796return s797798799def compress_nd(x, axis=None):800"""Suppress slices from multiple dimensions which contain masked values.801802Parameters803----------804x : array_like, MaskedArray805The array to operate on. If not a MaskedArray instance (or if no array806elements are masked), `x` is interpreted as a MaskedArray with `mask`807set to `nomask`.808axis : tuple of ints or int, optional809Which dimensions to suppress slices from can be configured with this810parameter.811- If axis is a tuple of ints, those are the axes to suppress slices from.812- If axis is an int, then that is the only axis to suppress slices from.813- If axis is None, all axis are selected.814815Returns816-------817compress_array : ndarray818The compressed array.819"""820x = asarray(x)821m = getmask(x)822# Set axis to tuple of ints823if axis is None:824axis = tuple(range(x.ndim))825else:826axis = normalize_axis_tuple(axis, x.ndim)827828# Nothing is masked: return x829if m is nomask or not m.any():830return x._data831# All is masked: return empty832if m.all():833return nxarray([])834# Filter elements through boolean indexing835data = x._data836for ax in axis:837axes = tuple(list(range(ax)) + list(range(ax + 1, x.ndim)))838data = data[(slice(None),)*ax + (~m.any(axis=axes),)]839return data840841def compress_rowcols(x, axis=None):842"""843Suppress the rows and/or columns of a 2-D array that contain844masked values.845846The suppression behavior is selected with the `axis` parameter.847848- If axis is None, both rows and columns are suppressed.849- If axis is 0, only rows are suppressed.850- If axis is 1 or -1, only columns are suppressed.851852Parameters853----------854x : array_like, MaskedArray855The array to operate on. If not a MaskedArray instance (or if no array856elements are masked), `x` is interpreted as a MaskedArray with857`mask` set to `nomask`. Must be a 2D array.858axis : int, optional859Axis along which to perform the operation. Default is None.860861Returns862-------863compressed_array : ndarray864The compressed array.865866Examples867--------868>>> x = np.ma.array(np.arange(9).reshape(3, 3), mask=[[1, 0, 0],869... [1, 0, 0],870... [0, 0, 0]])871>>> x872masked_array(873data=[[--, 1, 2],874[--, 4, 5],875[6, 7, 8]],876mask=[[ True, False, False],877[ True, False, False],878[False, False, False]],879fill_value=999999)880881>>> np.ma.compress_rowcols(x)882array([[7, 8]])883>>> np.ma.compress_rowcols(x, 0)884array([[6, 7, 8]])885>>> np.ma.compress_rowcols(x, 1)886array([[1, 2],887[4, 5],888[7, 8]])889890"""891if asarray(x).ndim != 2:892raise NotImplementedError("compress_rowcols works for 2D arrays only.")893return compress_nd(x, axis=axis)894895896def compress_rows(a):897"""898Suppress whole rows of a 2-D array that contain masked values.899900This is equivalent to ``np.ma.compress_rowcols(a, 0)``, see901`compress_rowcols` for details.902903See Also904--------905compress_rowcols906907"""908a = asarray(a)909if a.ndim != 2:910raise NotImplementedError("compress_rows works for 2D arrays only.")911return compress_rowcols(a, 0)912913def compress_cols(a):914"""915Suppress whole columns of a 2-D array that contain masked values.916917This is equivalent to ``np.ma.compress_rowcols(a, 1)``, see918`compress_rowcols` for details.919920See Also921--------922compress_rowcols923924"""925a = asarray(a)926if a.ndim != 2:927raise NotImplementedError("compress_cols works for 2D arrays only.")928return compress_rowcols(a, 1)929930def mask_rows(a, axis=np._NoValue):931"""932Mask rows of a 2D array that contain masked values.933934This function is a shortcut to ``mask_rowcols`` with `axis` equal to 0.935936See Also937--------938mask_rowcols : Mask rows and/or columns of a 2D array.939masked_where : Mask where a condition is met.940941Examples942--------943>>> import numpy.ma as ma944>>> a = np.zeros((3, 3), dtype=int)945>>> a[1, 1] = 1946>>> a947array([[0, 0, 0],948[0, 1, 0],949[0, 0, 0]])950>>> a = ma.masked_equal(a, 1)951>>> a952masked_array(953data=[[0, 0, 0],954[0, --, 0],955[0, 0, 0]],956mask=[[False, False, False],957[False, True, False],958[False, False, False]],959fill_value=1)960961>>> ma.mask_rows(a)962masked_array(963data=[[0, 0, 0],964[--, --, --],965[0, 0, 0]],966mask=[[False, False, False],967[ True, True, True],968[False, False, False]],969fill_value=1)970971"""972if axis is not np._NoValue:973# remove the axis argument when this deprecation expires974# NumPy 1.18.0, 2019-11-28975warnings.warn(976"The axis argument has always been ignored, in future passing it "977"will raise TypeError", DeprecationWarning, stacklevel=2)978return mask_rowcols(a, 0)979980def mask_cols(a, axis=np._NoValue):981"""982Mask columns of a 2D array that contain masked values.983984This function is a shortcut to ``mask_rowcols`` with `axis` equal to 1.985986See Also987--------988mask_rowcols : Mask rows and/or columns of a 2D array.989masked_where : Mask where a condition is met.990991Examples992--------993>>> import numpy.ma as ma994>>> a = np.zeros((3, 3), dtype=int)995>>> a[1, 1] = 1996>>> a997array([[0, 0, 0],998[0, 1, 0],999[0, 0, 0]])1000>>> a = ma.masked_equal(a, 1)1001>>> a1002masked_array(1003data=[[0, 0, 0],1004[0, --, 0],1005[0, 0, 0]],1006mask=[[False, False, False],1007[False, True, False],1008[False, False, False]],1009fill_value=1)1010>>> ma.mask_cols(a)1011masked_array(1012data=[[0, --, 0],1013[0, --, 0],1014[0, --, 0]],1015mask=[[False, True, False],1016[False, True, False],1017[False, True, False]],1018fill_value=1)10191020"""1021if axis is not np._NoValue:1022# remove the axis argument when this deprecation expires1023# NumPy 1.18.0, 2019-11-281024warnings.warn(1025"The axis argument has always been ignored, in future passing it "1026"will raise TypeError", DeprecationWarning, stacklevel=2)1027return mask_rowcols(a, 1)102810291030#####--------------------------------------------------------------------------1031#---- --- arraysetops ---1032#####--------------------------------------------------------------------------10331034def ediff1d(arr, to_end=None, to_begin=None):1035"""1036Compute the differences between consecutive elements of an array.10371038This function is the equivalent of `numpy.ediff1d` that takes masked1039values into account, see `numpy.ediff1d` for details.10401041See Also1042--------1043numpy.ediff1d : Equivalent function for ndarrays.10441045"""1046arr = ma.asanyarray(arr).flat1047ed = arr[1:] - arr[:-1]1048arrays = [ed]1049#1050if to_begin is not None:1051arrays.insert(0, to_begin)1052if to_end is not None:1053arrays.append(to_end)1054#1055if len(arrays) != 1:1056# We'll save ourselves a copy of a potentially large array in the common1057# case where neither to_begin or to_end was given.1058ed = hstack(arrays)1059#1060return ed106110621063def unique(ar1, return_index=False, return_inverse=False):1064"""1065Finds the unique elements of an array.10661067Masked values are considered the same element (masked). The output array1068is always a masked array. See `numpy.unique` for more details.10691070See Also1071--------1072numpy.unique : Equivalent function for ndarrays.10731074"""1075output = np.unique(ar1,1076return_index=return_index,1077return_inverse=return_inverse)1078if isinstance(output, tuple):1079output = list(output)1080output[0] = output[0].view(MaskedArray)1081output = tuple(output)1082else:1083output = output.view(MaskedArray)1084return output108510861087def intersect1d(ar1, ar2, assume_unique=False):1088"""1089Returns the unique elements common to both arrays.10901091Masked values are considered equal one to the other.1092The output is always a masked array.10931094See `numpy.intersect1d` for more details.10951096See Also1097--------1098numpy.intersect1d : Equivalent function for ndarrays.10991100Examples1101--------1102>>> x = np.ma.array([1, 3, 3, 3], mask=[0, 0, 0, 1])1103>>> y = np.ma.array([3, 1, 1, 1], mask=[0, 0, 0, 1])1104>>> np.ma.intersect1d(x, y)1105masked_array(data=[1, 3, --],1106mask=[False, False, True],1107fill_value=999999)11081109"""1110if assume_unique:1111aux = ma.concatenate((ar1, ar2))1112else:1113# Might be faster than unique( intersect1d( ar1, ar2 ) )?1114aux = ma.concatenate((unique(ar1), unique(ar2)))1115aux.sort()1116return aux[:-1][aux[1:] == aux[:-1]]111711181119def setxor1d(ar1, ar2, assume_unique=False):1120"""1121Set exclusive-or of 1-D arrays with unique elements.11221123The output is always a masked array. See `numpy.setxor1d` for more details.11241125See Also1126--------1127numpy.setxor1d : Equivalent function for ndarrays.11281129"""1130if not assume_unique:1131ar1 = unique(ar1)1132ar2 = unique(ar2)11331134aux = ma.concatenate((ar1, ar2))1135if aux.size == 0:1136return aux1137aux.sort()1138auxf = aux.filled()1139# flag = ediff1d( aux, to_end = 1, to_begin = 1 ) == 01140flag = ma.concatenate(([True], (auxf[1:] != auxf[:-1]), [True]))1141# flag2 = ediff1d( flag ) == 01142flag2 = (flag[1:] == flag[:-1])1143return aux[flag2]114411451146def in1d(ar1, ar2, assume_unique=False, invert=False):1147"""1148Test whether each element of an array is also present in a second1149array.11501151The output is always a masked array. See `numpy.in1d` for more details.11521153We recommend using :func:`isin` instead of `in1d` for new code.11541155See Also1156--------1157isin : Version of this function that preserves the shape of ar1.1158numpy.in1d : Equivalent function for ndarrays.11591160Notes1161-----1162.. versionadded:: 1.4.011631164"""1165if not assume_unique:1166ar1, rev_idx = unique(ar1, return_inverse=True)1167ar2 = unique(ar2)11681169ar = ma.concatenate((ar1, ar2))1170# We need this to be a stable sort, so always use 'mergesort'1171# here. The values from the first array should always come before1172# the values from the second array.1173order = ar.argsort(kind='mergesort')1174sar = ar[order]1175if invert:1176bool_ar = (sar[1:] != sar[:-1])1177else:1178bool_ar = (sar[1:] == sar[:-1])1179flag = ma.concatenate((bool_ar, [invert]))1180indx = order.argsort(kind='mergesort')[:len(ar1)]11811182if assume_unique:1183return flag[indx]1184else:1185return flag[indx][rev_idx]118611871188def isin(element, test_elements, assume_unique=False, invert=False):1189"""1190Calculates `element in test_elements`, broadcasting over1191`element` only.11921193The output is always a masked array of the same shape as `element`.1194See `numpy.isin` for more details.11951196See Also1197--------1198in1d : Flattened version of this function.1199numpy.isin : Equivalent function for ndarrays.12001201Notes1202-----1203.. versionadded:: 1.13.012041205"""1206element = ma.asarray(element)1207return in1d(element, test_elements, assume_unique=assume_unique,1208invert=invert).reshape(element.shape)120912101211def union1d(ar1, ar2):1212"""1213Union of two arrays.12141215The output is always a masked array. See `numpy.union1d` for more details.12161217See Also1218--------1219numpy.union1d : Equivalent function for ndarrays.12201221"""1222return unique(ma.concatenate((ar1, ar2), axis=None))122312241225def setdiff1d(ar1, ar2, assume_unique=False):1226"""1227Set difference of 1D arrays with unique elements.12281229The output is always a masked array. See `numpy.setdiff1d` for more1230details.12311232See Also1233--------1234numpy.setdiff1d : Equivalent function for ndarrays.12351236Examples1237--------1238>>> x = np.ma.array([1, 2, 3, 4], mask=[0, 1, 0, 1])1239>>> np.ma.setdiff1d(x, [1, 2])1240masked_array(data=[3, --],1241mask=[False, True],1242fill_value=999999)12431244"""1245if assume_unique:1246ar1 = ma.asarray(ar1).ravel()1247else:1248ar1 = unique(ar1)1249ar2 = unique(ar2)1250return ar1[in1d(ar1, ar2, assume_unique=True, invert=True)]125112521253###############################################################################1254# Covariance #1255###############################################################################125612571258def _covhelper(x, y=None, rowvar=True, allow_masked=True):1259"""1260Private function for the computation of covariance and correlation1261coefficients.12621263"""1264x = ma.array(x, ndmin=2, copy=True, dtype=float)1265xmask = ma.getmaskarray(x)1266# Quick exit if we can't process masked data1267if not allow_masked and xmask.any():1268raise ValueError("Cannot process masked data.")1269#1270if x.shape[0] == 1:1271rowvar = True1272# Make sure that rowvar is either 0 or 11273rowvar = int(bool(rowvar))1274axis = 1 - rowvar1275if rowvar:1276tup = (slice(None), None)1277else:1278tup = (None, slice(None))1279#1280if y is None:1281xnotmask = np.logical_not(xmask).astype(int)1282else:1283y = array(y, copy=False, ndmin=2, dtype=float)1284ymask = ma.getmaskarray(y)1285if not allow_masked and ymask.any():1286raise ValueError("Cannot process masked data.")1287if xmask.any() or ymask.any():1288if y.shape == x.shape:1289# Define some common mask1290common_mask = np.logical_or(xmask, ymask)1291if common_mask is not nomask:1292xmask = x._mask = y._mask = ymask = common_mask1293x._sharedmask = False1294y._sharedmask = False1295x = ma.concatenate((x, y), axis)1296xnotmask = np.logical_not(np.concatenate((xmask, ymask), axis)).astype(int)1297x -= x.mean(axis=rowvar)[tup]1298return (x, xnotmask, rowvar)129913001301def cov(x, y=None, rowvar=True, bias=False, allow_masked=True, ddof=None):1302"""1303Estimate the covariance matrix.13041305Except for the handling of missing data this function does the same as1306`numpy.cov`. For more details and examples, see `numpy.cov`.13071308By default, masked values are recognized as such. If `x` and `y` have the1309same shape, a common mask is allocated: if ``x[i,j]`` is masked, then1310``y[i,j]`` will also be masked.1311Setting `allow_masked` to False will raise an exception if values are1312missing in either of the input arrays.13131314Parameters1315----------1316x : array_like1317A 1-D or 2-D array containing multiple variables and observations.1318Each row of `x` represents a variable, and each column a single1319observation of all those variables. Also see `rowvar` below.1320y : array_like, optional1321An additional set of variables and observations. `y` has the same1322shape as `x`.1323rowvar : bool, optional1324If `rowvar` is True (default), then each row represents a1325variable, with observations in the columns. Otherwise, the relationship1326is transposed: each column represents a variable, while the rows1327contain observations.1328bias : bool, optional1329Default normalization (False) is by ``(N-1)``, where ``N`` is the1330number of observations given (unbiased estimate). If `bias` is True,1331then normalization is by ``N``. This keyword can be overridden by1332the keyword ``ddof`` in numpy versions >= 1.5.1333allow_masked : bool, optional1334If True, masked values are propagated pair-wise: if a value is masked1335in `x`, the corresponding value is masked in `y`.1336If False, raises a `ValueError` exception when some values are missing.1337ddof : {None, int}, optional1338If not ``None`` normalization is by ``(N - ddof)``, where ``N`` is1339the number of observations; this overrides the value implied by1340``bias``. The default value is ``None``.13411342.. versionadded:: 1.513431344Raises1345------1346ValueError1347Raised if some values are missing and `allow_masked` is False.13481349See Also1350--------1351numpy.cov13521353"""1354# Check inputs1355if ddof is not None and ddof != int(ddof):1356raise ValueError("ddof must be an integer")1357# Set up ddof1358if ddof is None:1359if bias:1360ddof = 01361else:1362ddof = 113631364(x, xnotmask, rowvar) = _covhelper(x, y, rowvar, allow_masked)1365if not rowvar:1366fact = np.dot(xnotmask.T, xnotmask) * 1. - ddof1367result = (dot(x.T, x.conj(), strict=False) / fact).squeeze()1368else:1369fact = np.dot(xnotmask, xnotmask.T) * 1. - ddof1370result = (dot(x, x.T.conj(), strict=False) / fact).squeeze()1371return result137213731374def corrcoef(x, y=None, rowvar=True, bias=np._NoValue, allow_masked=True,1375ddof=np._NoValue):1376"""1377Return Pearson product-moment correlation coefficients.13781379Except for the handling of missing data this function does the same as1380`numpy.corrcoef`. For more details and examples, see `numpy.corrcoef`.13811382Parameters1383----------1384x : array_like1385A 1-D or 2-D array containing multiple variables and observations.1386Each row of `x` represents a variable, and each column a single1387observation of all those variables. Also see `rowvar` below.1388y : array_like, optional1389An additional set of variables and observations. `y` has the same1390shape as `x`.1391rowvar : bool, optional1392If `rowvar` is True (default), then each row represents a1393variable, with observations in the columns. Otherwise, the relationship1394is transposed: each column represents a variable, while the rows1395contain observations.1396bias : _NoValue, optional1397Has no effect, do not use.13981399.. deprecated:: 1.10.01400allow_masked : bool, optional1401If True, masked values are propagated pair-wise: if a value is masked1402in `x`, the corresponding value is masked in `y`.1403If False, raises an exception. Because `bias` is deprecated, this1404argument needs to be treated as keyword only to avoid a warning.1405ddof : _NoValue, optional1406Has no effect, do not use.14071408.. deprecated:: 1.10.014091410See Also1411--------1412numpy.corrcoef : Equivalent function in top-level NumPy module.1413cov : Estimate the covariance matrix.14141415Notes1416-----1417This function accepts but discards arguments `bias` and `ddof`. This is1418for backwards compatibility with previous versions of this function. These1419arguments had no effect on the return values of the function and can be1420safely ignored in this and previous versions of numpy.1421"""1422msg = 'bias and ddof have no effect and are deprecated'1423if bias is not np._NoValue or ddof is not np._NoValue:1424# 2015-03-15, 1.101425warnings.warn(msg, DeprecationWarning, stacklevel=2)1426# Get the data1427(x, xnotmask, rowvar) = _covhelper(x, y, rowvar, allow_masked)1428# Compute the covariance matrix1429if not rowvar:1430fact = np.dot(xnotmask.T, xnotmask) * 1.1431c = (dot(x.T, x.conj(), strict=False) / fact).squeeze()1432else:1433fact = np.dot(xnotmask, xnotmask.T) * 1.1434c = (dot(x, x.T.conj(), strict=False) / fact).squeeze()1435# Check whether we have a scalar1436try:1437diag = ma.diagonal(c)1438except ValueError:1439return 11440#1441if xnotmask.all():1442_denom = ma.sqrt(ma.multiply.outer(diag, diag))1443else:1444_denom = diagflat(diag)1445_denom._sharedmask = False # We know return is always a copy1446n = x.shape[1 - rowvar]1447if rowvar:1448for i in range(n - 1):1449for j in range(i + 1, n):1450_x = mask_cols(vstack((x[i], x[j]))).var(axis=1)1451_denom[i, j] = _denom[j, i] = ma.sqrt(ma.multiply.reduce(_x))1452else:1453for i in range(n - 1):1454for j in range(i + 1, n):1455_x = mask_cols(1456vstack((x[:, i], x[:, j]))).var(axis=1)1457_denom[i, j] = _denom[j, i] = ma.sqrt(ma.multiply.reduce(_x))1458return c / _denom14591460#####--------------------------------------------------------------------------1461#---- --- Concatenation helpers ---1462#####--------------------------------------------------------------------------14631464class MAxisConcatenator(AxisConcatenator):1465"""1466Translate slice objects to concatenation along an axis.14671468For documentation on usage, see `mr_class`.14691470See Also1471--------1472mr_class14731474"""1475concatenate = staticmethod(concatenate)14761477@classmethod1478def makemat(cls, arr):1479# There used to be a view as np.matrix here, but we may eventually1480# deprecate that class. In preparation, we use the unmasked version1481# to construct the matrix (with copy=False for backwards compatibility1482# with the .view)1483data = super().makemat(arr.data, copy=False)1484return array(data, mask=arr.mask)14851486def __getitem__(self, key):1487# matrix builder syntax, like 'a, b; c, d'1488if isinstance(key, str):1489raise MAError("Unavailable for masked array.")14901491return super().__getitem__(key)149214931494class mr_class(MAxisConcatenator):1495"""1496Translate slice objects to concatenation along the first axis.14971498This is the masked array version of `lib.index_tricks.RClass`.14991500See Also1501--------1502lib.index_tricks.RClass15031504Examples1505--------1506>>> np.ma.mr_[np.ma.array([1,2,3]), 0, 0, np.ma.array([4,5,6])]1507masked_array(data=[1, 2, 3, ..., 4, 5, 6],1508mask=False,1509fill_value=999999)15101511"""1512def __init__(self):1513MAxisConcatenator.__init__(self, 0)15141515mr_ = mr_class()15161517#####--------------------------------------------------------------------------1518#---- Find unmasked data ---1519#####--------------------------------------------------------------------------15201521def flatnotmasked_edges(a):1522"""1523Find the indices of the first and last unmasked values.15241525Expects a 1-D `MaskedArray`, returns None if all values are masked.15261527Parameters1528----------1529a : array_like1530Input 1-D `MaskedArray`15311532Returns1533-------1534edges : ndarray or None1535The indices of first and last non-masked value in the array.1536Returns None if all values are masked.15371538See Also1539--------1540flatnotmasked_contiguous, notmasked_contiguous, notmasked_edges1541clump_masked, clump_unmasked15421543Notes1544-----1545Only accepts 1-D arrays.15461547Examples1548--------1549>>> a = np.ma.arange(10)1550>>> np.ma.flatnotmasked_edges(a)1551array([0, 9])15521553>>> mask = (a < 3) | (a > 8) | (a == 5)1554>>> a[mask] = np.ma.masked1555>>> np.array(a[~a.mask])1556array([3, 4, 6, 7, 8])15571558>>> np.ma.flatnotmasked_edges(a)1559array([3, 8])15601561>>> a[:] = np.ma.masked1562>>> print(np.ma.flatnotmasked_edges(a))1563None15641565"""1566m = getmask(a)1567if m is nomask or not np.any(m):1568return np.array([0, a.size - 1])1569unmasked = np.flatnonzero(~m)1570if len(unmasked) > 0:1571return unmasked[[0, -1]]1572else:1573return None157415751576def notmasked_edges(a, axis=None):1577"""1578Find the indices of the first and last unmasked values along an axis.15791580If all values are masked, return None. Otherwise, return a list1581of two tuples, corresponding to the indices of the first and last1582unmasked values respectively.15831584Parameters1585----------1586a : array_like1587The input array.1588axis : int, optional1589Axis along which to perform the operation.1590If None (default), applies to a flattened version of the array.15911592Returns1593-------1594edges : ndarray or list1595An array of start and end indexes if there are any masked data in1596the array. If there are no masked data in the array, `edges` is a1597list of the first and last index.15981599See Also1600--------1601flatnotmasked_contiguous, flatnotmasked_edges, notmasked_contiguous1602clump_masked, clump_unmasked16031604Examples1605--------1606>>> a = np.arange(9).reshape((3, 3))1607>>> m = np.zeros_like(a)1608>>> m[1:, 1:] = 116091610>>> am = np.ma.array(a, mask=m)1611>>> np.array(am[~am.mask])1612array([0, 1, 2, 3, 6])16131614>>> np.ma.notmasked_edges(am)1615array([0, 6])16161617"""1618a = asarray(a)1619if axis is None or a.ndim == 1:1620return flatnotmasked_edges(a)1621m = getmaskarray(a)1622idx = array(np.indices(a.shape), mask=np.asarray([m] * a.ndim))1623return [tuple([idx[i].min(axis).compressed() for i in range(a.ndim)]),1624tuple([idx[i].max(axis).compressed() for i in range(a.ndim)]), ]162516261627def flatnotmasked_contiguous(a):1628"""1629Find contiguous unmasked data in a masked array along the given axis.16301631Parameters1632----------1633a : narray1634The input array.16351636Returns1637-------1638slice_list : list1639A sorted sequence of `slice` objects (start index, end index).16401641.. versionchanged:: 1.15.01642Now returns an empty list instead of None for a fully masked array16431644See Also1645--------1646flatnotmasked_edges, notmasked_contiguous, notmasked_edges1647clump_masked, clump_unmasked16481649Notes1650-----1651Only accepts 2-D arrays at most.16521653Examples1654--------1655>>> a = np.ma.arange(10)1656>>> np.ma.flatnotmasked_contiguous(a)1657[slice(0, 10, None)]16581659>>> mask = (a < 3) | (a > 8) | (a == 5)1660>>> a[mask] = np.ma.masked1661>>> np.array(a[~a.mask])1662array([3, 4, 6, 7, 8])16631664>>> np.ma.flatnotmasked_contiguous(a)1665[slice(3, 5, None), slice(6, 9, None)]1666>>> a[:] = np.ma.masked1667>>> np.ma.flatnotmasked_contiguous(a)1668[]16691670"""1671m = getmask(a)1672if m is nomask:1673return [slice(0, a.size)]1674i = 01675result = []1676for (k, g) in itertools.groupby(m.ravel()):1677n = len(list(g))1678if not k:1679result.append(slice(i, i + n))1680i += n1681return result16821683def notmasked_contiguous(a, axis=None):1684"""1685Find contiguous unmasked data in a masked array along the given axis.16861687Parameters1688----------1689a : array_like1690The input array.1691axis : int, optional1692Axis along which to perform the operation.1693If None (default), applies to a flattened version of the array, and this1694is the same as `flatnotmasked_contiguous`.16951696Returns1697-------1698endpoints : list1699A list of slices (start and end indexes) of unmasked indexes1700in the array.17011702If the input is 2d and axis is specified, the result is a list of lists.17031704See Also1705--------1706flatnotmasked_edges, flatnotmasked_contiguous, notmasked_edges1707clump_masked, clump_unmasked17081709Notes1710-----1711Only accepts 2-D arrays at most.17121713Examples1714--------1715>>> a = np.arange(12).reshape((3, 4))1716>>> mask = np.zeros_like(a)1717>>> mask[1:, :-1] = 1; mask[0, 1] = 1; mask[-1, 0] = 01718>>> ma = np.ma.array(a, mask=mask)1719>>> ma1720masked_array(1721data=[[0, --, 2, 3],1722[--, --, --, 7],1723[8, --, --, 11]],1724mask=[[False, True, False, False],1725[ True, True, True, False],1726[False, True, True, False]],1727fill_value=999999)1728>>> np.array(ma[~ma.mask])1729array([ 0, 2, 3, 7, 8, 11])17301731>>> np.ma.notmasked_contiguous(ma)1732[slice(0, 1, None), slice(2, 4, None), slice(7, 9, None), slice(11, 12, None)]17331734>>> np.ma.notmasked_contiguous(ma, axis=0)1735[[slice(0, 1, None), slice(2, 3, None)], [], [slice(0, 1, None)], [slice(0, 3, None)]]17361737>>> np.ma.notmasked_contiguous(ma, axis=1)1738[[slice(0, 1, None), slice(2, 4, None)], [slice(3, 4, None)], [slice(0, 1, None), slice(3, 4, None)]]17391740"""1741a = asarray(a)1742nd = a.ndim1743if nd > 2:1744raise NotImplementedError("Currently limited to atmost 2D array.")1745if axis is None or nd == 1:1746return flatnotmasked_contiguous(a)1747#1748result = []1749#1750other = (axis + 1) % 21751idx = [0, 0]1752idx[axis] = slice(None, None)1753#1754for i in range(a.shape[other]):1755idx[other] = i1756result.append(flatnotmasked_contiguous(a[tuple(idx)]))1757return result175817591760def _ezclump(mask):1761"""1762Finds the clumps (groups of data with the same values) for a 1D bool array.17631764Returns a series of slices.1765"""1766if mask.ndim > 1:1767mask = mask.ravel()1768idx = (mask[1:] ^ mask[:-1]).nonzero()1769idx = idx[0] + 117701771if mask[0]:1772if len(idx) == 0:1773return [slice(0, mask.size)]17741775r = [slice(0, idx[0])]1776r.extend((slice(left, right)1777for left, right in zip(idx[1:-1:2], idx[2::2])))1778else:1779if len(idx) == 0:1780return []17811782r = [slice(left, right) for left, right in zip(idx[:-1:2], idx[1::2])]17831784if mask[-1]:1785r.append(slice(idx[-1], mask.size))1786return r178717881789def clump_unmasked(a):1790"""1791Return list of slices corresponding to the unmasked clumps of a 1-D array.1792(A "clump" is defined as a contiguous region of the array).17931794Parameters1795----------1796a : ndarray1797A one-dimensional masked array.17981799Returns1800-------1801slices : list of slice1802The list of slices, one for each continuous region of unmasked1803elements in `a`.18041805Notes1806-----1807.. versionadded:: 1.4.018081809See Also1810--------1811flatnotmasked_edges, flatnotmasked_contiguous, notmasked_edges1812notmasked_contiguous, clump_masked18131814Examples1815--------1816>>> a = np.ma.masked_array(np.arange(10))1817>>> a[[0, 1, 2, 6, 8, 9]] = np.ma.masked1818>>> np.ma.clump_unmasked(a)1819[slice(3, 6, None), slice(7, 8, None)]18201821"""1822mask = getattr(a, '_mask', nomask)1823if mask is nomask:1824return [slice(0, a.size)]1825return _ezclump(~mask)182618271828def clump_masked(a):1829"""1830Returns a list of slices corresponding to the masked clumps of a 1-D array.1831(A "clump" is defined as a contiguous region of the array).18321833Parameters1834----------1835a : ndarray1836A one-dimensional masked array.18371838Returns1839-------1840slices : list of slice1841The list of slices, one for each continuous region of masked elements1842in `a`.18431844Notes1845-----1846.. versionadded:: 1.4.018471848See Also1849--------1850flatnotmasked_edges, flatnotmasked_contiguous, notmasked_edges1851notmasked_contiguous, clump_unmasked18521853Examples1854--------1855>>> a = np.ma.masked_array(np.arange(10))1856>>> a[[0, 1, 2, 6, 8, 9]] = np.ma.masked1857>>> np.ma.clump_masked(a)1858[slice(0, 3, None), slice(6, 7, None), slice(8, 10, None)]18591860"""1861mask = ma.getmask(a)1862if mask is nomask:1863return []1864return _ezclump(mask)186518661867###############################################################################1868# Polynomial fit #1869###############################################################################187018711872def vander(x, n=None):1873"""1874Masked values in the input array result in rows of zeros.18751876"""1877_vander = np.vander(x, n)1878m = getmask(x)1879if m is not nomask:1880_vander[m] = 01881return _vander18821883vander.__doc__ = ma.doc_note(np.vander.__doc__, vander.__doc__)188418851886def polyfit(x, y, deg, rcond=None, full=False, w=None, cov=False):1887"""1888Any masked values in x is propagated in y, and vice-versa.18891890"""1891x = asarray(x)1892y = asarray(y)18931894m = getmask(x)1895if y.ndim == 1:1896m = mask_or(m, getmask(y))1897elif y.ndim == 2:1898my = getmask(mask_rows(y))1899if my is not nomask:1900m = mask_or(m, my[:, 0])1901else:1902raise TypeError("Expected a 1D or 2D array for y!")19031904if w is not None:1905w = asarray(w)1906if w.ndim != 1:1907raise TypeError("expected a 1-d array for weights")1908if w.shape[0] != y.shape[0]:1909raise TypeError("expected w and y to have the same length")1910m = mask_or(m, getmask(w))19111912if m is not nomask:1913not_m = ~m1914if w is not None:1915w = w[not_m]1916return np.polyfit(x[not_m], y[not_m], deg, rcond, full, w, cov)1917else:1918return np.polyfit(x, y, deg, rcond, full, w, cov)19191920polyfit.__doc__ = ma.doc_note(np.polyfit.__doc__, polyfit.__doc__)192119221923