Coverage for /home/martinb/.local/share/virtualenvs/camcops/lib/python3.6/site-packages/numpy/ma/core.py : 26%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1"""
2numpy.ma : a package to handle missing or invalid values.
4This package was initially written for numarray by Paul F. Dubois
5at Lawrence Livermore National Laboratory.
6In 2006, the package was completely rewritten by Pierre Gerard-Marchant
7(University of Georgia) to make the MaskedArray class a subclass of ndarray,
8and to improve support of structured arrays.
11Copyright 1999, 2000, 2001 Regents of the University of California.
12Released for unlimited redistribution.
14* Adapted for numpy_core 2005 by Travis Oliphant and (mainly) Paul Dubois.
15* Subclassing of the base `ndarray` 2006 by Pierre Gerard-Marchant
16 (pgmdevlist_AT_gmail_DOT_com)
17* Improvements suggested by Reggie Dugard (reggie_AT_merfinllc_DOT_com)
19.. moduleauthor:: Pierre Gerard-Marchant
21"""
22# pylint: disable-msg=E1002
23import builtins
24import operator
25import warnings
26import textwrap
27import re
28from functools import reduce
30import numpy as np
31import numpy.core.umath as umath
32import numpy.core.numerictypes as ntypes
33from numpy import ndarray, amax, amin, iscomplexobj, bool_, _NoValue
34from numpy import array as narray
35from numpy.lib.function_base import angle
36from numpy.compat import (
37 getargspec, formatargspec, long, unicode, bytes
38 )
39from numpy import expand_dims
40from numpy.core.numeric import normalize_axis_tuple
41from numpy.core._internal import recursive
42from numpy.compat import pickle
45__all__ = [
46 'MAError', 'MaskError', 'MaskType', 'MaskedArray', 'abs', 'absolute',
47 'add', 'all', 'allclose', 'allequal', 'alltrue', 'amax', 'amin',
48 'angle', 'anom', 'anomalies', 'any', 'append', 'arange', 'arccos',
49 'arccosh', 'arcsin', 'arcsinh', 'arctan', 'arctan2', 'arctanh',
50 'argmax', 'argmin', 'argsort', 'around', 'array', 'asanyarray',
51 'asarray', 'bitwise_and', 'bitwise_or', 'bitwise_xor', 'bool_', 'ceil',
52 'choose', 'clip', 'common_fill_value', 'compress', 'compressed',
53 'concatenate', 'conjugate', 'convolve', 'copy', 'correlate', 'cos', 'cosh',
54 'count', 'cumprod', 'cumsum', 'default_fill_value', 'diag', 'diagonal',
55 'diff', 'divide', 'empty', 'empty_like', 'equal', 'exp',
56 'expand_dims', 'fabs', 'filled', 'fix_invalid', 'flatten_mask',
57 'flatten_structured_array', 'floor', 'floor_divide', 'fmod',
58 'frombuffer', 'fromflex', 'fromfunction', 'getdata', 'getmask',
59 'getmaskarray', 'greater', 'greater_equal', 'harden_mask', 'hypot',
60 'identity', 'ids', 'indices', 'inner', 'innerproduct', 'isMA',
61 'isMaskedArray', 'is_mask', 'is_masked', 'isarray', 'left_shift',
62 'less', 'less_equal', 'log', 'log10', 'log2',
63 'logical_and', 'logical_not', 'logical_or', 'logical_xor', 'make_mask',
64 'make_mask_descr', 'make_mask_none', 'mask_or', 'masked',
65 'masked_array', 'masked_equal', 'masked_greater',
66 'masked_greater_equal', 'masked_inside', 'masked_invalid',
67 'masked_less', 'masked_less_equal', 'masked_not_equal',
68 'masked_object', 'masked_outside', 'masked_print_option',
69 'masked_singleton', 'masked_values', 'masked_where', 'max', 'maximum',
70 'maximum_fill_value', 'mean', 'min', 'minimum', 'minimum_fill_value',
71 'mod', 'multiply', 'mvoid', 'ndim', 'negative', 'nomask', 'nonzero',
72 'not_equal', 'ones', 'outer', 'outerproduct', 'power', 'prod',
73 'product', 'ptp', 'put', 'putmask', 'ravel', 'remainder',
74 'repeat', 'reshape', 'resize', 'right_shift', 'round', 'round_',
75 'set_fill_value', 'shape', 'sin', 'sinh', 'size', 'soften_mask',
76 'sometrue', 'sort', 'sqrt', 'squeeze', 'std', 'subtract', 'sum',
77 'swapaxes', 'take', 'tan', 'tanh', 'trace', 'transpose', 'true_divide',
78 'var', 'where', 'zeros',
79 ]
81MaskType = np.bool_
82nomask = MaskType(0)
84class MaskedArrayFutureWarning(FutureWarning):
85 pass
87def _deprecate_argsort_axis(arr):
88 """
89 Adjust the axis passed to argsort, warning if necessary
91 Parameters
92 ----------
93 arr
94 The array which argsort was called on
96 np.ma.argsort has a long-term bug where the default of the axis argument
97 is wrong (gh-8701), which now must be kept for backwards compatibility.
98 Thankfully, this only makes a difference when arrays are 2- or more-
99 dimensional, so we only need a warning then.
100 """
101 if arr.ndim <= 1:
102 # no warning needed - but switch to -1 anyway, to avoid surprising
103 # subclasses, which are more likely to implement scalar axes.
104 return -1
105 else:
106 # 2017-04-11, Numpy 1.13.0, gh-8701: warn on axis default
107 warnings.warn(
108 "In the future the default for argsort will be axis=-1, not the "
109 "current None, to match its documentation and np.argsort. "
110 "Explicitly pass -1 or None to silence this warning.",
111 MaskedArrayFutureWarning, stacklevel=3)
112 return None
115def doc_note(initialdoc, note):
116 """
117 Adds a Notes section to an existing docstring.
119 """
120 if initialdoc is None:
121 return
122 if note is None:
123 return initialdoc
125 notesplit = re.split(r'\n\s*?Notes\n\s*?-----', initialdoc)
127 notedoc = """\
128Notes
129 -----
130 %s""" % note
132 if len(notesplit) > 1:
133 notedoc = '\n\n ' + notedoc + '\n'
135 return ''.join(notesplit[:1] + [notedoc] + notesplit[1:])
138def get_object_signature(obj):
139 """
140 Get the signature from obj
142 """
143 try:
144 sig = formatargspec(*getargspec(obj))
145 except TypeError:
146 sig = ''
147 return sig
150###############################################################################
151# Exceptions #
152###############################################################################
155class MAError(Exception):
156 """
157 Class for masked array related errors.
159 """
160 pass
163class MaskError(MAError):
164 """
165 Class for mask related errors.
167 """
168 pass
171###############################################################################
172# Filling options #
173###############################################################################
176# b: boolean - c: complex - f: floats - i: integer - O: object - S: string
177default_filler = {'b': True,
178 'c': 1.e20 + 0.0j,
179 'f': 1.e20,
180 'i': 999999,
181 'O': '?',
182 'S': b'N/A',
183 'u': 999999,
184 'V': b'???',
185 'U': u'N/A'
186 }
188# Add datetime64 and timedelta64 types
189for v in ["Y", "M", "W", "D", "h", "m", "s", "ms", "us", "ns", "ps",
190 "fs", "as"]:
191 default_filler["M8[" + v + "]"] = np.datetime64("NaT", v)
192 default_filler["m8[" + v + "]"] = np.timedelta64("NaT", v)
194float_types_list = [np.half, np.single, np.double, np.longdouble,
195 np.csingle, np.cdouble, np.clongdouble]
196max_filler = ntypes._minvals
197max_filler.update([(k, -np.inf) for k in float_types_list[:4]])
198max_filler.update([(k, complex(-np.inf, -np.inf)) for k in float_types_list[-3:]])
200min_filler = ntypes._maxvals
201min_filler.update([(k, +np.inf) for k in float_types_list[:4]])
202min_filler.update([(k, complex(+np.inf, +np.inf)) for k in float_types_list[-3:]])
204del float_types_list
206def _recursive_fill_value(dtype, f):
207 """
208 Recursively produce a fill value for `dtype`, calling f on scalar dtypes
209 """
210 if dtype.names is not None:
211 vals = tuple(_recursive_fill_value(dtype[name], f) for name in dtype.names)
212 return np.array(vals, dtype=dtype)[()] # decay to void scalar from 0d
213 elif dtype.subdtype:
214 subtype, shape = dtype.subdtype
215 subval = _recursive_fill_value(subtype, f)
216 return np.full(shape, subval)
217 else:
218 return f(dtype)
221def _get_dtype_of(obj):
222 """ Convert the argument for *_fill_value into a dtype """
223 if isinstance(obj, np.dtype):
224 return obj
225 elif hasattr(obj, 'dtype'):
226 return obj.dtype
227 else:
228 return np.asanyarray(obj).dtype
231def default_fill_value(obj):
232 """
233 Return the default fill value for the argument object.
235 The default filling value depends on the datatype of the input
236 array or the type of the input scalar:
238 ======== ========
239 datatype default
240 ======== ========
241 bool True
242 int 999999
243 float 1.e20
244 complex 1.e20+0j
245 object '?'
246 string 'N/A'
247 ======== ========
249 For structured types, a structured scalar is returned, with each field the
250 default fill value for its type.
252 For subarray types, the fill value is an array of the same size containing
253 the default scalar fill value.
255 Parameters
256 ----------
257 obj : ndarray, dtype or scalar
258 The array data-type or scalar for which the default fill value
259 is returned.
261 Returns
262 -------
263 fill_value : scalar
264 The default fill value.
266 Examples
267 --------
268 >>> np.ma.default_fill_value(1)
269 999999
270 >>> np.ma.default_fill_value(np.array([1.1, 2., np.pi]))
271 1e+20
272 >>> np.ma.default_fill_value(np.dtype(complex))
273 (1e+20+0j)
275 """
276 def _scalar_fill_value(dtype):
277 if dtype.kind in 'Mm':
278 return default_filler.get(dtype.str[1:], '?')
279 else:
280 return default_filler.get(dtype.kind, '?')
282 dtype = _get_dtype_of(obj)
283 return _recursive_fill_value(dtype, _scalar_fill_value)
286def _extremum_fill_value(obj, extremum, extremum_name):
288 def _scalar_fill_value(dtype):
289 try:
290 return extremum[dtype]
291 except KeyError as e:
292 raise TypeError(
293 f"Unsuitable type {dtype} for calculating {extremum_name}."
294 ) from None
296 dtype = _get_dtype_of(obj)
297 return _recursive_fill_value(dtype, _scalar_fill_value)
300def minimum_fill_value(obj):
301 """
302 Return the maximum value that can be represented by the dtype of an object.
304 This function is useful for calculating a fill value suitable for
305 taking the minimum of an array with a given dtype.
307 Parameters
308 ----------
309 obj : ndarray, dtype or scalar
310 An object that can be queried for it's numeric type.
312 Returns
313 -------
314 val : scalar
315 The maximum representable value.
317 Raises
318 ------
319 TypeError
320 If `obj` isn't a suitable numeric type.
322 See Also
323 --------
324 maximum_fill_value : The inverse function.
325 set_fill_value : Set the filling value of a masked array.
326 MaskedArray.fill_value : Return current fill value.
328 Examples
329 --------
330 >>> import numpy.ma as ma
331 >>> a = np.int8()
332 >>> ma.minimum_fill_value(a)
333 127
334 >>> a = np.int32()
335 >>> ma.minimum_fill_value(a)
336 2147483647
338 An array of numeric data can also be passed.
340 >>> a = np.array([1, 2, 3], dtype=np.int8)
341 >>> ma.minimum_fill_value(a)
342 127
343 >>> a = np.array([1, 2, 3], dtype=np.float32)
344 >>> ma.minimum_fill_value(a)
345 inf
347 """
348 return _extremum_fill_value(obj, min_filler, "minimum")
351def maximum_fill_value(obj):
352 """
353 Return the minimum value that can be represented by the dtype of an object.
355 This function is useful for calculating a fill value suitable for
356 taking the maximum of an array with a given dtype.
358 Parameters
359 ----------
360 obj : ndarray, dtype or scalar
361 An object that can be queried for it's numeric type.
363 Returns
364 -------
365 val : scalar
366 The minimum representable value.
368 Raises
369 ------
370 TypeError
371 If `obj` isn't a suitable numeric type.
373 See Also
374 --------
375 minimum_fill_value : The inverse function.
376 set_fill_value : Set the filling value of a masked array.
377 MaskedArray.fill_value : Return current fill value.
379 Examples
380 --------
381 >>> import numpy.ma as ma
382 >>> a = np.int8()
383 >>> ma.maximum_fill_value(a)
384 -128
385 >>> a = np.int32()
386 >>> ma.maximum_fill_value(a)
387 -2147483648
389 An array of numeric data can also be passed.
391 >>> a = np.array([1, 2, 3], dtype=np.int8)
392 >>> ma.maximum_fill_value(a)
393 -128
394 >>> a = np.array([1, 2, 3], dtype=np.float32)
395 >>> ma.maximum_fill_value(a)
396 -inf
398 """
399 return _extremum_fill_value(obj, max_filler, "maximum")
402def _recursive_set_fill_value(fillvalue, dt):
403 """
404 Create a fill value for a structured dtype.
406 Parameters
407 ----------
408 fillvalue: scalar or array_like
409 Scalar or array representing the fill value. If it is of shorter
410 length than the number of fields in dt, it will be resized.
411 dt: dtype
412 The structured dtype for which to create the fill value.
414 Returns
415 -------
416 val: tuple
417 A tuple of values corresponding to the structured fill value.
419 """
420 fillvalue = np.resize(fillvalue, len(dt.names))
421 output_value = []
422 for (fval, name) in zip(fillvalue, dt.names):
423 cdtype = dt[name]
424 if cdtype.subdtype:
425 cdtype = cdtype.subdtype[0]
427 if cdtype.names is not None:
428 output_value.append(tuple(_recursive_set_fill_value(fval, cdtype)))
429 else:
430 output_value.append(np.array(fval, dtype=cdtype).item())
431 return tuple(output_value)
434def _check_fill_value(fill_value, ndtype):
435 """
436 Private function validating the given `fill_value` for the given dtype.
438 If fill_value is None, it is set to the default corresponding to the dtype.
440 If fill_value is not None, its value is forced to the given dtype.
442 The result is always a 0d array.
444 """
445 ndtype = np.dtype(ndtype)
446 if fill_value is None:
447 fill_value = default_fill_value(ndtype)
448 elif ndtype.names is not None:
449 if isinstance(fill_value, (ndarray, np.void)):
450 try:
451 fill_value = np.array(fill_value, copy=False, dtype=ndtype)
452 except ValueError:
453 err_msg = "Unable to transform %s to dtype %s"
454 raise ValueError(err_msg % (fill_value, ndtype))
455 else:
456 fill_value = np.asarray(fill_value, dtype=object)
457 fill_value = np.array(_recursive_set_fill_value(fill_value, ndtype),
458 dtype=ndtype)
459 else:
460 if isinstance(fill_value, str) and (ndtype.char not in 'OSVU'):
461 # Note this check doesn't work if fill_value is not a scalar
462 err_msg = "Cannot set fill value of string with array of dtype %s"
463 raise TypeError(err_msg % ndtype)
464 else:
465 # In case we want to convert 1e20 to int.
466 # Also in case of converting string arrays.
467 try:
468 fill_value = np.array(fill_value, copy=False, dtype=ndtype)
469 except (OverflowError, ValueError):
470 # Raise TypeError instead of OverflowError or ValueError.
471 # OverflowError is seldom used, and the real problem here is
472 # that the passed fill_value is not compatible with the ndtype.
473 err_msg = "Cannot convert fill_value %s to dtype %s"
474 raise TypeError(err_msg % (fill_value, ndtype))
475 return np.array(fill_value)
478def set_fill_value(a, fill_value):
479 """
480 Set the filling value of a, if a is a masked array.
482 This function changes the fill value of the masked array `a` in place.
483 If `a` is not a masked array, the function returns silently, without
484 doing anything.
486 Parameters
487 ----------
488 a : array_like
489 Input array.
490 fill_value : dtype
491 Filling value. A consistency test is performed to make sure
492 the value is compatible with the dtype of `a`.
494 Returns
495 -------
496 None
497 Nothing returned by this function.
499 See Also
500 --------
501 maximum_fill_value : Return the default fill value for a dtype.
502 MaskedArray.fill_value : Return current fill value.
503 MaskedArray.set_fill_value : Equivalent method.
505 Examples
506 --------
507 >>> import numpy.ma as ma
508 >>> a = np.arange(5)
509 >>> a
510 array([0, 1, 2, 3, 4])
511 >>> a = ma.masked_where(a < 3, a)
512 >>> a
513 masked_array(data=[--, --, --, 3, 4],
514 mask=[ True, True, True, False, False],
515 fill_value=999999)
516 >>> ma.set_fill_value(a, -999)
517 >>> a
518 masked_array(data=[--, --, --, 3, 4],
519 mask=[ True, True, True, False, False],
520 fill_value=-999)
522 Nothing happens if `a` is not a masked array.
524 >>> a = list(range(5))
525 >>> a
526 [0, 1, 2, 3, 4]
527 >>> ma.set_fill_value(a, 100)
528 >>> a
529 [0, 1, 2, 3, 4]
530 >>> a = np.arange(5)
531 >>> a
532 array([0, 1, 2, 3, 4])
533 >>> ma.set_fill_value(a, 100)
534 >>> a
535 array([0, 1, 2, 3, 4])
537 """
538 if isinstance(a, MaskedArray):
539 a.set_fill_value(fill_value)
540 return
543def get_fill_value(a):
544 """
545 Return the filling value of a, if any. Otherwise, returns the
546 default filling value for that type.
548 """
549 if isinstance(a, MaskedArray):
550 result = a.fill_value
551 else:
552 result = default_fill_value(a)
553 return result
556def common_fill_value(a, b):
557 """
558 Return the common filling value of two masked arrays, if any.
560 If ``a.fill_value == b.fill_value``, return the fill value,
561 otherwise return None.
563 Parameters
564 ----------
565 a, b : MaskedArray
566 The masked arrays for which to compare fill values.
568 Returns
569 -------
570 fill_value : scalar or None
571 The common fill value, or None.
573 Examples
574 --------
575 >>> x = np.ma.array([0, 1.], fill_value=3)
576 >>> y = np.ma.array([0, 1.], fill_value=3)
577 >>> np.ma.common_fill_value(x, y)
578 3.0
580 """
581 t1 = get_fill_value(a)
582 t2 = get_fill_value(b)
583 if t1 == t2:
584 return t1
585 return None
588def filled(a, fill_value=None):
589 """
590 Return input as an array with masked data replaced by a fill value.
592 If `a` is not a `MaskedArray`, `a` itself is returned.
593 If `a` is a `MaskedArray` and `fill_value` is None, `fill_value` is set to
594 ``a.fill_value``.
596 Parameters
597 ----------
598 a : MaskedArray or array_like
599 An input object.
600 fill_value : array_like, optional.
601 Can be scalar or non-scalar. If non-scalar, the
602 resulting filled array should be broadcastable
603 over input array. Default is None.
605 Returns
606 -------
607 a : ndarray
608 The filled array.
610 See Also
611 --------
612 compressed
614 Examples
615 --------
616 >>> x = np.ma.array(np.arange(9).reshape(3, 3), mask=[[1, 0, 0],
617 ... [1, 0, 0],
618 ... [0, 0, 0]])
619 >>> x.filled()
620 array([[999999, 1, 2],
621 [999999, 4, 5],
622 [ 6, 7, 8]])
623 >>> x.filled(fill_value=333)
624 array([[333, 1, 2],
625 [333, 4, 5],
626 [ 6, 7, 8]])
627 >>> x.filled(fill_value=np.arange(3))
628 array([[0, 1, 2],
629 [0, 4, 5],
630 [6, 7, 8]])
632 """
633 if hasattr(a, 'filled'):
634 return a.filled(fill_value)
636 elif isinstance(a, ndarray):
637 # Should we check for contiguity ? and a.flags['CONTIGUOUS']:
638 return a
639 elif isinstance(a, dict):
640 return np.array(a, 'O')
641 else:
642 return np.array(a)
645def get_masked_subclass(*arrays):
646 """
647 Return the youngest subclass of MaskedArray from a list of (masked) arrays.
649 In case of siblings, the first listed takes over.
651 """
652 if len(arrays) == 1:
653 arr = arrays[0]
654 if isinstance(arr, MaskedArray):
655 rcls = type(arr)
656 else:
657 rcls = MaskedArray
658 else:
659 arrcls = [type(a) for a in arrays]
660 rcls = arrcls[0]
661 if not issubclass(rcls, MaskedArray):
662 rcls = MaskedArray
663 for cls in arrcls[1:]:
664 if issubclass(cls, rcls):
665 rcls = cls
666 # Don't return MaskedConstant as result: revert to MaskedArray
667 if rcls.__name__ == 'MaskedConstant':
668 return MaskedArray
669 return rcls
672def getdata(a, subok=True):
673 """
674 Return the data of a masked array as an ndarray.
676 Return the data of `a` (if any) as an ndarray if `a` is a ``MaskedArray``,
677 else return `a` as a ndarray or subclass (depending on `subok`) if not.
679 Parameters
680 ----------
681 a : array_like
682 Input ``MaskedArray``, alternatively a ndarray or a subclass thereof.
683 subok : bool
684 Whether to force the output to be a `pure` ndarray (False) or to
685 return a subclass of ndarray if appropriate (True, default).
687 See Also
688 --------
689 getmask : Return the mask of a masked array, or nomask.
690 getmaskarray : Return the mask of a masked array, or full array of False.
692 Examples
693 --------
694 >>> import numpy.ma as ma
695 >>> a = ma.masked_equal([[1,2],[3,4]], 2)
696 >>> a
697 masked_array(
698 data=[[1, --],
699 [3, 4]],
700 mask=[[False, True],
701 [False, False]],
702 fill_value=2)
703 >>> ma.getdata(a)
704 array([[1, 2],
705 [3, 4]])
707 Equivalently use the ``MaskedArray`` `data` attribute.
709 >>> a.data
710 array([[1, 2],
711 [3, 4]])
713 """
714 try:
715 data = a._data
716 except AttributeError:
717 data = np.array(a, copy=False, subok=subok)
718 if not subok:
719 return data.view(ndarray)
720 return data
723get_data = getdata
726def fix_invalid(a, mask=nomask, copy=True, fill_value=None):
727 """
728 Return input with invalid data masked and replaced by a fill value.
730 Invalid data means values of `nan`, `inf`, etc.
732 Parameters
733 ----------
734 a : array_like
735 Input array, a (subclass of) ndarray.
736 mask : sequence, optional
737 Mask. Must be convertible to an array of booleans with the same
738 shape as `data`. True indicates a masked (i.e. invalid) data.
739 copy : bool, optional
740 Whether to use a copy of `a` (True) or to fix `a` in place (False).
741 Default is True.
742 fill_value : scalar, optional
743 Value used for fixing invalid data. Default is None, in which case
744 the ``a.fill_value`` is used.
746 Returns
747 -------
748 b : MaskedArray
749 The input array with invalid entries fixed.
751 Notes
752 -----
753 A copy is performed by default.
755 Examples
756 --------
757 >>> x = np.ma.array([1., -1, np.nan, np.inf], mask=[1] + [0]*3)
758 >>> x
759 masked_array(data=[--, -1.0, nan, inf],
760 mask=[ True, False, False, False],
761 fill_value=1e+20)
762 >>> np.ma.fix_invalid(x)
763 masked_array(data=[--, -1.0, --, --],
764 mask=[ True, False, True, True],
765 fill_value=1e+20)
767 >>> fixed = np.ma.fix_invalid(x)
768 >>> fixed.data
769 array([ 1.e+00, -1.e+00, 1.e+20, 1.e+20])
770 >>> x.data
771 array([ 1., -1., nan, inf])
773 """
774 a = masked_array(a, copy=copy, mask=mask, subok=True)
775 invalid = np.logical_not(np.isfinite(a._data))
776 if not invalid.any():
777 return a
778 a._mask |= invalid
779 if fill_value is None:
780 fill_value = a.fill_value
781 a._data[invalid] = fill_value
782 return a
784def is_string_or_list_of_strings(val):
785 return (isinstance(val, str) or
786 (isinstance(val, list) and val and
787 builtins.all(isinstance(s, str) for s in val)))
789###############################################################################
790# Ufuncs #
791###############################################################################
794ufunc_domain = {}
795ufunc_fills = {}
798class _DomainCheckInterval:
799 """
800 Define a valid interval, so that :
802 ``domain_check_interval(a,b)(x) == True`` where
803 ``x < a`` or ``x > b``.
805 """
807 def __init__(self, a, b):
808 "domain_check_interval(a,b)(x) = true where x < a or y > b"
809 if a > b:
810 (a, b) = (b, a)
811 self.a = a
812 self.b = b
814 def __call__(self, x):
815 "Execute the call behavior."
816 # nans at masked positions cause RuntimeWarnings, even though
817 # they are masked. To avoid this we suppress warnings.
818 with np.errstate(invalid='ignore'):
819 return umath.logical_or(umath.greater(x, self.b),
820 umath.less(x, self.a))
823class _DomainTan:
824 """
825 Define a valid interval for the `tan` function, so that:
827 ``domain_tan(eps) = True`` where ``abs(cos(x)) < eps``
829 """
831 def __init__(self, eps):
832 "domain_tan(eps) = true where abs(cos(x)) < eps)"
833 self.eps = eps
835 def __call__(self, x):
836 "Executes the call behavior."
837 with np.errstate(invalid='ignore'):
838 return umath.less(umath.absolute(umath.cos(x)), self.eps)
841class _DomainSafeDivide:
842 """
843 Define a domain for safe division.
845 """
847 def __init__(self, tolerance=None):
848 self.tolerance = tolerance
850 def __call__(self, a, b):
851 # Delay the selection of the tolerance to here in order to reduce numpy
852 # import times. The calculation of these parameters is a substantial
853 # component of numpy's import time.
854 if self.tolerance is None:
855 self.tolerance = np.finfo(float).tiny
856 # don't call ma ufuncs from __array_wrap__ which would fail for scalars
857 a, b = np.asarray(a), np.asarray(b)
858 with np.errstate(invalid='ignore'):
859 return umath.absolute(a) * self.tolerance >= umath.absolute(b)
862class _DomainGreater:
863 """
864 DomainGreater(v)(x) is True where x <= v.
866 """
868 def __init__(self, critical_value):
869 "DomainGreater(v)(x) = true where x <= v"
870 self.critical_value = critical_value
872 def __call__(self, x):
873 "Executes the call behavior."
874 with np.errstate(invalid='ignore'):
875 return umath.less_equal(x, self.critical_value)
878class _DomainGreaterEqual:
879 """
880 DomainGreaterEqual(v)(x) is True where x < v.
882 """
884 def __init__(self, critical_value):
885 "DomainGreaterEqual(v)(x) = true where x < v"
886 self.critical_value = critical_value
888 def __call__(self, x):
889 "Executes the call behavior."
890 with np.errstate(invalid='ignore'):
891 return umath.less(x, self.critical_value)
894class _MaskedUFunc:
895 def __init__(self, ufunc):
896 self.f = ufunc
897 self.__doc__ = ufunc.__doc__
898 self.__name__ = ufunc.__name__
900 def __str__(self):
901 return f"Masked version of {self.f}"
904class _MaskedUnaryOperation(_MaskedUFunc):
905 """
906 Defines masked version of unary operations, where invalid values are
907 pre-masked.
909 Parameters
910 ----------
911 mufunc : callable
912 The function for which to define a masked version. Made available
913 as ``_MaskedUnaryOperation.f``.
914 fill : scalar, optional
915 Filling value, default is 0.
916 domain : class instance
917 Domain for the function. Should be one of the ``_Domain*``
918 classes. Default is None.
920 """
922 def __init__(self, mufunc, fill=0, domain=None):
923 super(_MaskedUnaryOperation, self).__init__(mufunc)
924 self.fill = fill
925 self.domain = domain
926 ufunc_domain[mufunc] = domain
927 ufunc_fills[mufunc] = fill
929 def __call__(self, a, *args, **kwargs):
930 """
931 Execute the call behavior.
933 """
934 d = getdata(a)
935 # Deal with domain
936 if self.domain is not None:
937 # Case 1.1. : Domained function
938 # nans at masked positions cause RuntimeWarnings, even though
939 # they are masked. To avoid this we suppress warnings.
940 with np.errstate(divide='ignore', invalid='ignore'):
941 result = self.f(d, *args, **kwargs)
942 # Make a mask
943 m = ~umath.isfinite(result)
944 m |= self.domain(d)
945 m |= getmask(a)
946 else:
947 # Case 1.2. : Function without a domain
948 # Get the result and the mask
949 with np.errstate(divide='ignore', invalid='ignore'):
950 result = self.f(d, *args, **kwargs)
951 m = getmask(a)
953 if not result.ndim:
954 # Case 2.1. : The result is scalarscalar
955 if m:
956 return masked
957 return result
959 if m is not nomask:
960 # Case 2.2. The result is an array
961 # We need to fill the invalid data back w/ the input Now,
962 # that's plain silly: in C, we would just skip the element and
963 # keep the original, but we do have to do it that way in Python
965 # In case result has a lower dtype than the inputs (as in
966 # equal)
967 try:
968 np.copyto(result, d, where=m)
969 except TypeError:
970 pass
971 # Transform to
972 masked_result = result.view(get_masked_subclass(a))
973 masked_result._mask = m
974 masked_result._update_from(a)
975 return masked_result
978class _MaskedBinaryOperation(_MaskedUFunc):
979 """
980 Define masked version of binary operations, where invalid
981 values are pre-masked.
983 Parameters
984 ----------
985 mbfunc : function
986 The function for which to define a masked version. Made available
987 as ``_MaskedBinaryOperation.f``.
988 domain : class instance
989 Default domain for the function. Should be one of the ``_Domain*``
990 classes. Default is None.
991 fillx : scalar, optional
992 Filling value for the first argument, default is 0.
993 filly : scalar, optional
994 Filling value for the second argument, default is 0.
996 """
998 def __init__(self, mbfunc, fillx=0, filly=0):
999 """
1000 abfunc(fillx, filly) must be defined.
1002 abfunc(x, filly) = x for all x to enable reduce.
1004 """
1005 super(_MaskedBinaryOperation, self).__init__(mbfunc)
1006 self.fillx = fillx
1007 self.filly = filly
1008 ufunc_domain[mbfunc] = None
1009 ufunc_fills[mbfunc] = (fillx, filly)
1011 def __call__(self, a, b, *args, **kwargs):
1012 """
1013 Execute the call behavior.
1015 """
1016 # Get the data, as ndarray
1017 (da, db) = (getdata(a), getdata(b))
1018 # Get the result
1019 with np.errstate():
1020 np.seterr(divide='ignore', invalid='ignore')
1021 result = self.f(da, db, *args, **kwargs)
1022 # Get the mask for the result
1023 (ma, mb) = (getmask(a), getmask(b))
1024 if ma is nomask:
1025 if mb is nomask:
1026 m = nomask
1027 else:
1028 m = umath.logical_or(getmaskarray(a), mb)
1029 elif mb is nomask:
1030 m = umath.logical_or(ma, getmaskarray(b))
1031 else:
1032 m = umath.logical_or(ma, mb)
1034 # Case 1. : scalar
1035 if not result.ndim:
1036 if m:
1037 return masked
1038 return result
1040 # Case 2. : array
1041 # Revert result to da where masked
1042 if m is not nomask and m.any():
1043 # any errors, just abort; impossible to guarantee masked values
1044 try:
1045 np.copyto(result, da, casting='unsafe', where=m)
1046 except Exception:
1047 pass
1049 # Transforms to a (subclass of) MaskedArray
1050 masked_result = result.view(get_masked_subclass(a, b))
1051 masked_result._mask = m
1052 if isinstance(a, MaskedArray):
1053 masked_result._update_from(a)
1054 elif isinstance(b, MaskedArray):
1055 masked_result._update_from(b)
1056 return masked_result
1058 def reduce(self, target, axis=0, dtype=None):
1059 """
1060 Reduce `target` along the given `axis`.
1062 """
1063 tclass = get_masked_subclass(target)
1064 m = getmask(target)
1065 t = filled(target, self.filly)
1066 if t.shape == ():
1067 t = t.reshape(1)
1068 if m is not nomask:
1069 m = make_mask(m, copy=True)
1070 m.shape = (1,)
1072 if m is nomask:
1073 tr = self.f.reduce(t, axis)
1074 mr = nomask
1075 else:
1076 tr = self.f.reduce(t, axis, dtype=dtype or t.dtype)
1077 mr = umath.logical_and.reduce(m, axis)
1079 if not tr.shape:
1080 if mr:
1081 return masked
1082 else:
1083 return tr
1084 masked_tr = tr.view(tclass)
1085 masked_tr._mask = mr
1086 return masked_tr
1088 def outer(self, a, b):
1089 """
1090 Return the function applied to the outer product of a and b.
1092 """
1093 (da, db) = (getdata(a), getdata(b))
1094 d = self.f.outer(da, db)
1095 ma = getmask(a)
1096 mb = getmask(b)
1097 if ma is nomask and mb is nomask:
1098 m = nomask
1099 else:
1100 ma = getmaskarray(a)
1101 mb = getmaskarray(b)
1102 m = umath.logical_or.outer(ma, mb)
1103 if (not m.ndim) and m:
1104 return masked
1105 if m is not nomask:
1106 np.copyto(d, da, where=m)
1107 if not d.shape:
1108 return d
1109 masked_d = d.view(get_masked_subclass(a, b))
1110 masked_d._mask = m
1111 return masked_d
1113 def accumulate(self, target, axis=0):
1114 """Accumulate `target` along `axis` after filling with y fill
1115 value.
1117 """
1118 tclass = get_masked_subclass(target)
1119 t = filled(target, self.filly)
1120 result = self.f.accumulate(t, axis)
1121 masked_result = result.view(tclass)
1122 return masked_result
1126class _DomainedBinaryOperation(_MaskedUFunc):
1127 """
1128 Define binary operations that have a domain, like divide.
1130 They have no reduce, outer or accumulate.
1132 Parameters
1133 ----------
1134 mbfunc : function
1135 The function for which to define a masked version. Made available
1136 as ``_DomainedBinaryOperation.f``.
1137 domain : class instance
1138 Default domain for the function. Should be one of the ``_Domain*``
1139 classes.
1140 fillx : scalar, optional
1141 Filling value for the first argument, default is 0.
1142 filly : scalar, optional
1143 Filling value for the second argument, default is 0.
1145 """
1147 def __init__(self, dbfunc, domain, fillx=0, filly=0):
1148 """abfunc(fillx, filly) must be defined.
1149 abfunc(x, filly) = x for all x to enable reduce.
1150 """
1151 super(_DomainedBinaryOperation, self).__init__(dbfunc)
1152 self.domain = domain
1153 self.fillx = fillx
1154 self.filly = filly
1155 ufunc_domain[dbfunc] = domain
1156 ufunc_fills[dbfunc] = (fillx, filly)
1158 def __call__(self, a, b, *args, **kwargs):
1159 "Execute the call behavior."
1160 # Get the data
1161 (da, db) = (getdata(a), getdata(b))
1162 # Get the result
1163 with np.errstate(divide='ignore', invalid='ignore'):
1164 result = self.f(da, db, *args, **kwargs)
1165 # Get the mask as a combination of the source masks and invalid
1166 m = ~umath.isfinite(result)
1167 m |= getmask(a)
1168 m |= getmask(b)
1169 # Apply the domain
1170 domain = ufunc_domain.get(self.f, None)
1171 if domain is not None:
1172 m |= domain(da, db)
1173 # Take care of the scalar case first
1174 if not m.ndim:
1175 if m:
1176 return masked
1177 else:
1178 return result
1179 # When the mask is True, put back da if possible
1180 # any errors, just abort; impossible to guarantee masked values
1181 try:
1182 np.copyto(result, 0, casting='unsafe', where=m)
1183 # avoid using "*" since this may be overlaid
1184 masked_da = umath.multiply(m, da)
1185 # only add back if it can be cast safely
1186 if np.can_cast(masked_da.dtype, result.dtype, casting='safe'):
1187 result += masked_da
1188 except Exception:
1189 pass
1191 # Transforms to a (subclass of) MaskedArray
1192 masked_result = result.view(get_masked_subclass(a, b))
1193 masked_result._mask = m
1194 if isinstance(a, MaskedArray):
1195 masked_result._update_from(a)
1196 elif isinstance(b, MaskedArray):
1197 masked_result._update_from(b)
1198 return masked_result
1201# Unary ufuncs
1202exp = _MaskedUnaryOperation(umath.exp)
1203conjugate = _MaskedUnaryOperation(umath.conjugate)
1204sin = _MaskedUnaryOperation(umath.sin)
1205cos = _MaskedUnaryOperation(umath.cos)
1206arctan = _MaskedUnaryOperation(umath.arctan)
1207arcsinh = _MaskedUnaryOperation(umath.arcsinh)
1208sinh = _MaskedUnaryOperation(umath.sinh)
1209cosh = _MaskedUnaryOperation(umath.cosh)
1210tanh = _MaskedUnaryOperation(umath.tanh)
1211abs = absolute = _MaskedUnaryOperation(umath.absolute)
1212angle = _MaskedUnaryOperation(angle) # from numpy.lib.function_base
1213fabs = _MaskedUnaryOperation(umath.fabs)
1214negative = _MaskedUnaryOperation(umath.negative)
1215floor = _MaskedUnaryOperation(umath.floor)
1216ceil = _MaskedUnaryOperation(umath.ceil)
1217around = _MaskedUnaryOperation(np.round_)
1218logical_not = _MaskedUnaryOperation(umath.logical_not)
1220# Domained unary ufuncs
1221sqrt = _MaskedUnaryOperation(umath.sqrt, 0.0,
1222 _DomainGreaterEqual(0.0))
1223log = _MaskedUnaryOperation(umath.log, 1.0,
1224 _DomainGreater(0.0))
1225log2 = _MaskedUnaryOperation(umath.log2, 1.0,
1226 _DomainGreater(0.0))
1227log10 = _MaskedUnaryOperation(umath.log10, 1.0,
1228 _DomainGreater(0.0))
1229tan = _MaskedUnaryOperation(umath.tan, 0.0,
1230 _DomainTan(1e-35))
1231arcsin = _MaskedUnaryOperation(umath.arcsin, 0.0,
1232 _DomainCheckInterval(-1.0, 1.0))
1233arccos = _MaskedUnaryOperation(umath.arccos, 0.0,
1234 _DomainCheckInterval(-1.0, 1.0))
1235arccosh = _MaskedUnaryOperation(umath.arccosh, 1.0,
1236 _DomainGreaterEqual(1.0))
1237arctanh = _MaskedUnaryOperation(umath.arctanh, 0.0,
1238 _DomainCheckInterval(-1.0 + 1e-15, 1.0 - 1e-15))
1240# Binary ufuncs
1241add = _MaskedBinaryOperation(umath.add)
1242subtract = _MaskedBinaryOperation(umath.subtract)
1243multiply = _MaskedBinaryOperation(umath.multiply, 1, 1)
1244arctan2 = _MaskedBinaryOperation(umath.arctan2, 0.0, 1.0)
1245equal = _MaskedBinaryOperation(umath.equal)
1246equal.reduce = None
1247not_equal = _MaskedBinaryOperation(umath.not_equal)
1248not_equal.reduce = None
1249less_equal = _MaskedBinaryOperation(umath.less_equal)
1250less_equal.reduce = None
1251greater_equal = _MaskedBinaryOperation(umath.greater_equal)
1252greater_equal.reduce = None
1253less = _MaskedBinaryOperation(umath.less)
1254less.reduce = None
1255greater = _MaskedBinaryOperation(umath.greater)
1256greater.reduce = None
1257logical_and = _MaskedBinaryOperation(umath.logical_and)
1258alltrue = _MaskedBinaryOperation(umath.logical_and, 1, 1).reduce
1259logical_or = _MaskedBinaryOperation(umath.logical_or)
1260sometrue = logical_or.reduce
1261logical_xor = _MaskedBinaryOperation(umath.logical_xor)
1262bitwise_and = _MaskedBinaryOperation(umath.bitwise_and)
1263bitwise_or = _MaskedBinaryOperation(umath.bitwise_or)
1264bitwise_xor = _MaskedBinaryOperation(umath.bitwise_xor)
1265hypot = _MaskedBinaryOperation(umath.hypot)
1267# Domained binary ufuncs
1268divide = _DomainedBinaryOperation(umath.divide, _DomainSafeDivide(), 0, 1)
1269true_divide = _DomainedBinaryOperation(umath.true_divide,
1270 _DomainSafeDivide(), 0, 1)
1271floor_divide = _DomainedBinaryOperation(umath.floor_divide,
1272 _DomainSafeDivide(), 0, 1)
1273remainder = _DomainedBinaryOperation(umath.remainder,
1274 _DomainSafeDivide(), 0, 1)
1275fmod = _DomainedBinaryOperation(umath.fmod, _DomainSafeDivide(), 0, 1)
1276mod = _DomainedBinaryOperation(umath.mod, _DomainSafeDivide(), 0, 1)
1279###############################################################################
1280# Mask creation functions #
1281###############################################################################
1284def _replace_dtype_fields_recursive(dtype, primitive_dtype):
1285 "Private function allowing recursion in _replace_dtype_fields."
1286 _recurse = _replace_dtype_fields_recursive
1288 # Do we have some name fields ?
1289 if dtype.names is not None:
1290 descr = []
1291 for name in dtype.names:
1292 field = dtype.fields[name]
1293 if len(field) == 3:
1294 # Prepend the title to the name
1295 name = (field[-1], name)
1296 descr.append((name, _recurse(field[0], primitive_dtype)))
1297 new_dtype = np.dtype(descr)
1299 # Is this some kind of composite a la (float,2)
1300 elif dtype.subdtype:
1301 descr = list(dtype.subdtype)
1302 descr[0] = _recurse(dtype.subdtype[0], primitive_dtype)
1303 new_dtype = np.dtype(tuple(descr))
1305 # this is a primitive type, so do a direct replacement
1306 else:
1307 new_dtype = primitive_dtype
1309 # preserve identity of dtypes
1310 if new_dtype == dtype:
1311 new_dtype = dtype
1313 return new_dtype
1316def _replace_dtype_fields(dtype, primitive_dtype):
1317 """
1318 Construct a dtype description list from a given dtype.
1320 Returns a new dtype object, with all fields and subtypes in the given type
1321 recursively replaced with `primitive_dtype`.
1323 Arguments are coerced to dtypes first.
1324 """
1325 dtype = np.dtype(dtype)
1326 primitive_dtype = np.dtype(primitive_dtype)
1327 return _replace_dtype_fields_recursive(dtype, primitive_dtype)
1330def make_mask_descr(ndtype):
1331 """
1332 Construct a dtype description list from a given dtype.
1334 Returns a new dtype object, with the type of all fields in `ndtype` to a
1335 boolean type. Field names are not altered.
1337 Parameters
1338 ----------
1339 ndtype : dtype
1340 The dtype to convert.
1342 Returns
1343 -------
1344 result : dtype
1345 A dtype that looks like `ndtype`, the type of all fields is boolean.
1347 Examples
1348 --------
1349 >>> import numpy.ma as ma
1350 >>> dtype = np.dtype({'names':['foo', 'bar'],
1351 ... 'formats':[np.float32, np.int64]})
1352 >>> dtype
1353 dtype([('foo', '<f4'), ('bar', '<i8')])
1354 >>> ma.make_mask_descr(dtype)
1355 dtype([('foo', '|b1'), ('bar', '|b1')])
1356 >>> ma.make_mask_descr(np.float32)
1357 dtype('bool')
1359 """
1360 return _replace_dtype_fields(ndtype, MaskType)
1363def getmask(a):
1364 """
1365 Return the mask of a masked array, or nomask.
1367 Return the mask of `a` as an ndarray if `a` is a `MaskedArray` and the
1368 mask is not `nomask`, else return `nomask`. To guarantee a full array
1369 of booleans of the same shape as a, use `getmaskarray`.
1371 Parameters
1372 ----------
1373 a : array_like
1374 Input `MaskedArray` for which the mask is required.
1376 See Also
1377 --------
1378 getdata : Return the data of a masked array as an ndarray.
1379 getmaskarray : Return the mask of a masked array, or full array of False.
1381 Examples
1382 --------
1383 >>> import numpy.ma as ma
1384 >>> a = ma.masked_equal([[1,2],[3,4]], 2)
1385 >>> a
1386 masked_array(
1387 data=[[1, --],
1388 [3, 4]],
1389 mask=[[False, True],
1390 [False, False]],
1391 fill_value=2)
1392 >>> ma.getmask(a)
1393 array([[False, True],
1394 [False, False]])
1396 Equivalently use the `MaskedArray` `mask` attribute.
1398 >>> a.mask
1399 array([[False, True],
1400 [False, False]])
1402 Result when mask == `nomask`
1404 >>> b = ma.masked_array([[1,2],[3,4]])
1405 >>> b
1406 masked_array(
1407 data=[[1, 2],
1408 [3, 4]],
1409 mask=False,
1410 fill_value=999999)
1411 >>> ma.nomask
1412 False
1413 >>> ma.getmask(b) == ma.nomask
1414 True
1415 >>> b.mask == ma.nomask
1416 True
1418 """
1419 return getattr(a, '_mask', nomask)
1422get_mask = getmask
1425def getmaskarray(arr):
1426 """
1427 Return the mask of a masked array, or full boolean array of False.
1429 Return the mask of `arr` as an ndarray if `arr` is a `MaskedArray` and
1430 the mask is not `nomask`, else return a full boolean array of False of
1431 the same shape as `arr`.
1433 Parameters
1434 ----------
1435 arr : array_like
1436 Input `MaskedArray` for which the mask is required.
1438 See Also
1439 --------
1440 getmask : Return the mask of a masked array, or nomask.
1441 getdata : Return the data of a masked array as an ndarray.
1443 Examples
1444 --------
1445 >>> import numpy.ma as ma
1446 >>> a = ma.masked_equal([[1,2],[3,4]], 2)
1447 >>> a
1448 masked_array(
1449 data=[[1, --],
1450 [3, 4]],
1451 mask=[[False, True],
1452 [False, False]],
1453 fill_value=2)
1454 >>> ma.getmaskarray(a)
1455 array([[False, True],
1456 [False, False]])
1458 Result when mask == ``nomask``
1460 >>> b = ma.masked_array([[1,2],[3,4]])
1461 >>> b
1462 masked_array(
1463 data=[[1, 2],
1464 [3, 4]],
1465 mask=False,
1466 fill_value=999999)
1467 >>> ma.getmaskarray(b)
1468 array([[False, False],
1469 [False, False]])
1471 """
1472 mask = getmask(arr)
1473 if mask is nomask:
1474 mask = make_mask_none(np.shape(arr), getattr(arr, 'dtype', None))
1475 return mask
1478def is_mask(m):
1479 """
1480 Return True if m is a valid, standard mask.
1482 This function does not check the contents of the input, only that the
1483 type is MaskType. In particular, this function returns False if the
1484 mask has a flexible dtype.
1486 Parameters
1487 ----------
1488 m : array_like
1489 Array to test.
1491 Returns
1492 -------
1493 result : bool
1494 True if `m.dtype.type` is MaskType, False otherwise.
1496 See Also
1497 --------
1498 isMaskedArray : Test whether input is an instance of MaskedArray.
1500 Examples
1501 --------
1502 >>> import numpy.ma as ma
1503 >>> m = ma.masked_equal([0, 1, 0, 2, 3], 0)
1504 >>> m
1505 masked_array(data=[--, 1, --, 2, 3],
1506 mask=[ True, False, True, False, False],
1507 fill_value=0)
1508 >>> ma.is_mask(m)
1509 False
1510 >>> ma.is_mask(m.mask)
1511 True
1513 Input must be an ndarray (or have similar attributes)
1514 for it to be considered a valid mask.
1516 >>> m = [False, True, False]
1517 >>> ma.is_mask(m)
1518 False
1519 >>> m = np.array([False, True, False])
1520 >>> m
1521 array([False, True, False])
1522 >>> ma.is_mask(m)
1523 True
1525 Arrays with complex dtypes don't return True.
1527 >>> dtype = np.dtype({'names':['monty', 'pithon'],
1528 ... 'formats':[bool, bool]})
1529 >>> dtype
1530 dtype([('monty', '|b1'), ('pithon', '|b1')])
1531 >>> m = np.array([(True, False), (False, True), (True, False)],
1532 ... dtype=dtype)
1533 >>> m
1534 array([( True, False), (False, True), ( True, False)],
1535 dtype=[('monty', '?'), ('pithon', '?')])
1536 >>> ma.is_mask(m)
1537 False
1539 """
1540 try:
1541 return m.dtype.type is MaskType
1542 except AttributeError:
1543 return False
1546def _shrink_mask(m):
1547 """
1548 Shrink a mask to nomask if possible
1549 """
1550 if m.dtype.names is None and not m.any():
1551 return nomask
1552 else:
1553 return m
1556def make_mask(m, copy=False, shrink=True, dtype=MaskType):
1557 """
1558 Create a boolean mask from an array.
1560 Return `m` as a boolean mask, creating a copy if necessary or requested.
1561 The function can accept any sequence that is convertible to integers,
1562 or ``nomask``. Does not require that contents must be 0s and 1s, values
1563 of 0 are interpreted as False, everything else as True.
1565 Parameters
1566 ----------
1567 m : array_like
1568 Potential mask.
1569 copy : bool, optional
1570 Whether to return a copy of `m` (True) or `m` itself (False).
1571 shrink : bool, optional
1572 Whether to shrink `m` to ``nomask`` if all its values are False.
1573 dtype : dtype, optional
1574 Data-type of the output mask. By default, the output mask has a
1575 dtype of MaskType (bool). If the dtype is flexible, each field has
1576 a boolean dtype. This is ignored when `m` is ``nomask``, in which
1577 case ``nomask`` is always returned.
1579 Returns
1580 -------
1581 result : ndarray
1582 A boolean mask derived from `m`.
1584 Examples
1585 --------
1586 >>> import numpy.ma as ma
1587 >>> m = [True, False, True, True]
1588 >>> ma.make_mask(m)
1589 array([ True, False, True, True])
1590 >>> m = [1, 0, 1, 1]
1591 >>> ma.make_mask(m)
1592 array([ True, False, True, True])
1593 >>> m = [1, 0, 2, -3]
1594 >>> ma.make_mask(m)
1595 array([ True, False, True, True])
1597 Effect of the `shrink` parameter.
1599 >>> m = np.zeros(4)
1600 >>> m
1601 array([0., 0., 0., 0.])
1602 >>> ma.make_mask(m)
1603 False
1604 >>> ma.make_mask(m, shrink=False)
1605 array([False, False, False, False])
1607 Using a flexible `dtype`.
1609 >>> m = [1, 0, 1, 1]
1610 >>> n = [0, 1, 0, 0]
1611 >>> arr = []
1612 >>> for man, mouse in zip(m, n):
1613 ... arr.append((man, mouse))
1614 >>> arr
1615 [(1, 0), (0, 1), (1, 0), (1, 0)]
1616 >>> dtype = np.dtype({'names':['man', 'mouse'],
1617 ... 'formats':[np.int64, np.int64]})
1618 >>> arr = np.array(arr, dtype=dtype)
1619 >>> arr
1620 array([(1, 0), (0, 1), (1, 0), (1, 0)],
1621 dtype=[('man', '<i8'), ('mouse', '<i8')])
1622 >>> ma.make_mask(arr, dtype=dtype)
1623 array([(True, False), (False, True), (True, False), (True, False)],
1624 dtype=[('man', '|b1'), ('mouse', '|b1')])
1626 """
1627 if m is nomask:
1628 return nomask
1630 # Make sure the input dtype is valid.
1631 dtype = make_mask_descr(dtype)
1633 # legacy boolean special case: "existence of fields implies true"
1634 if isinstance(m, ndarray) and m.dtype.fields and dtype == np.bool_:
1635 return np.ones(m.shape, dtype=dtype)
1637 # Fill the mask in case there are missing data; turn it into an ndarray.
1638 result = np.array(filled(m, True), copy=copy, dtype=dtype, subok=True)
1639 # Bas les masques !
1640 if shrink:
1641 result = _shrink_mask(result)
1642 return result
1645def make_mask_none(newshape, dtype=None):
1646 """
1647 Return a boolean mask of the given shape, filled with False.
1649 This function returns a boolean ndarray with all entries False, that can
1650 be used in common mask manipulations. If a complex dtype is specified, the
1651 type of each field is converted to a boolean type.
1653 Parameters
1654 ----------
1655 newshape : tuple
1656 A tuple indicating the shape of the mask.
1657 dtype : {None, dtype}, optional
1658 If None, use a MaskType instance. Otherwise, use a new datatype with
1659 the same fields as `dtype`, converted to boolean types.
1661 Returns
1662 -------
1663 result : ndarray
1664 An ndarray of appropriate shape and dtype, filled with False.
1666 See Also
1667 --------
1668 make_mask : Create a boolean mask from an array.
1669 make_mask_descr : Construct a dtype description list from a given dtype.
1671 Examples
1672 --------
1673 >>> import numpy.ma as ma
1674 >>> ma.make_mask_none((3,))
1675 array([False, False, False])
1677 Defining a more complex dtype.
1679 >>> dtype = np.dtype({'names':['foo', 'bar'],
1680 ... 'formats':[np.float32, np.int64]})
1681 >>> dtype
1682 dtype([('foo', '<f4'), ('bar', '<i8')])
1683 >>> ma.make_mask_none((3,), dtype=dtype)
1684 array([(False, False), (False, False), (False, False)],
1685 dtype=[('foo', '|b1'), ('bar', '|b1')])
1687 """
1688 if dtype is None:
1689 result = np.zeros(newshape, dtype=MaskType)
1690 else:
1691 result = np.zeros(newshape, dtype=make_mask_descr(dtype))
1692 return result
1695def mask_or(m1, m2, copy=False, shrink=True):
1696 """
1697 Combine two masks with the ``logical_or`` operator.
1699 The result may be a view on `m1` or `m2` if the other is `nomask`
1700 (i.e. False).
1702 Parameters
1703 ----------
1704 m1, m2 : array_like
1705 Input masks.
1706 copy : bool, optional
1707 If copy is False and one of the inputs is `nomask`, return a view
1708 of the other input mask. Defaults to False.
1709 shrink : bool, optional
1710 Whether to shrink the output to `nomask` if all its values are
1711 False. Defaults to True.
1713 Returns
1714 -------
1715 mask : output mask
1716 The result masks values that are masked in either `m1` or `m2`.
1718 Raises
1719 ------
1720 ValueError
1721 If `m1` and `m2` have different flexible dtypes.
1723 Examples
1724 --------
1725 >>> m1 = np.ma.make_mask([0, 1, 1, 0])
1726 >>> m2 = np.ma.make_mask([1, 0, 0, 0])
1727 >>> np.ma.mask_or(m1, m2)
1728 array([ True, True, True, False])
1730 """
1732 @recursive
1733 def _recursive_mask_or(self, m1, m2, newmask):
1734 names = m1.dtype.names
1735 for name in names:
1736 current1 = m1[name]
1737 if current1.dtype.names is not None:
1738 self(current1, m2[name], newmask[name])
1739 else:
1740 umath.logical_or(current1, m2[name], newmask[name])
1741 return
1743 if (m1 is nomask) or (m1 is False):
1744 dtype = getattr(m2, 'dtype', MaskType)
1745 return make_mask(m2, copy=copy, shrink=shrink, dtype=dtype)
1746 if (m2 is nomask) or (m2 is False):
1747 dtype = getattr(m1, 'dtype', MaskType)
1748 return make_mask(m1, copy=copy, shrink=shrink, dtype=dtype)
1749 if m1 is m2 and is_mask(m1):
1750 return m1
1751 (dtype1, dtype2) = (getattr(m1, 'dtype', None), getattr(m2, 'dtype', None))
1752 if dtype1 != dtype2:
1753 raise ValueError("Incompatible dtypes '%s'<>'%s'" % (dtype1, dtype2))
1754 if dtype1.names is not None:
1755 # Allocate an output mask array with the properly broadcast shape.
1756 newmask = np.empty(np.broadcast(m1, m2).shape, dtype1)
1757 _recursive_mask_or(m1, m2, newmask)
1758 return newmask
1759 return make_mask(umath.logical_or(m1, m2), copy=copy, shrink=shrink)
1762def flatten_mask(mask):
1763 """
1764 Returns a completely flattened version of the mask, where nested fields
1765 are collapsed.
1767 Parameters
1768 ----------
1769 mask : array_like
1770 Input array, which will be interpreted as booleans.
1772 Returns
1773 -------
1774 flattened_mask : ndarray of bools
1775 The flattened input.
1777 Examples
1778 --------
1779 >>> mask = np.array([0, 0, 1])
1780 >>> np.ma.flatten_mask(mask)
1781 array([False, False, True])
1783 >>> mask = np.array([(0, 0), (0, 1)], dtype=[('a', bool), ('b', bool)])
1784 >>> np.ma.flatten_mask(mask)
1785 array([False, False, False, True])
1787 >>> mdtype = [('a', bool), ('b', [('ba', bool), ('bb', bool)])]
1788 >>> mask = np.array([(0, (0, 0)), (0, (0, 1))], dtype=mdtype)
1789 >>> np.ma.flatten_mask(mask)
1790 array([False, False, False, False, False, True])
1792 """
1794 def _flatmask(mask):
1795 "Flatten the mask and returns a (maybe nested) sequence of booleans."
1796 mnames = mask.dtype.names
1797 if mnames is not None:
1798 return [flatten_mask(mask[name]) for name in mnames]
1799 else:
1800 return mask
1802 def _flatsequence(sequence):
1803 "Generates a flattened version of the sequence."
1804 try:
1805 for element in sequence:
1806 if hasattr(element, '__iter__'):
1807 yield from _flatsequence(element)
1808 else:
1809 yield element
1810 except TypeError:
1811 yield sequence
1813 mask = np.asarray(mask)
1814 flattened = _flatsequence(_flatmask(mask))
1815 return np.array([_ for _ in flattened], dtype=bool)
1818def _check_mask_axis(mask, axis, keepdims=np._NoValue):
1819 "Check whether there are masked values along the given axis"
1820 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims}
1821 if mask is not nomask:
1822 return mask.all(axis=axis, **kwargs)
1823 return nomask
1826###############################################################################
1827# Masking functions #
1828###############################################################################
1830def masked_where(condition, a, copy=True):
1831 """
1832 Mask an array where a condition is met.
1834 Return `a` as an array masked where `condition` is True.
1835 Any masked values of `a` or `condition` are also masked in the output.
1837 Parameters
1838 ----------
1839 condition : array_like
1840 Masking condition. When `condition` tests floating point values for
1841 equality, consider using ``masked_values`` instead.
1842 a : array_like
1843 Array to mask.
1844 copy : bool
1845 If True (default) make a copy of `a` in the result. If False modify
1846 `a` in place and return a view.
1848 Returns
1849 -------
1850 result : MaskedArray
1851 The result of masking `a` where `condition` is True.
1853 See Also
1854 --------
1855 masked_values : Mask using floating point equality.
1856 masked_equal : Mask where equal to a given value.
1857 masked_not_equal : Mask where `not` equal to a given value.
1858 masked_less_equal : Mask where less than or equal to a given value.
1859 masked_greater_equal : Mask where greater than or equal to a given value.
1860 masked_less : Mask where less than a given value.
1861 masked_greater : Mask where greater than a given value.
1862 masked_inside : Mask inside a given interval.
1863 masked_outside : Mask outside a given interval.
1864 masked_invalid : Mask invalid values (NaNs or infs).
1866 Examples
1867 --------
1868 >>> import numpy.ma as ma
1869 >>> a = np.arange(4)
1870 >>> a
1871 array([0, 1, 2, 3])
1872 >>> ma.masked_where(a <= 2, a)
1873 masked_array(data=[--, --, --, 3],
1874 mask=[ True, True, True, False],
1875 fill_value=999999)
1877 Mask array `b` conditional on `a`.
1879 >>> b = ['a', 'b', 'c', 'd']
1880 >>> ma.masked_where(a == 2, b)
1881 masked_array(data=['a', 'b', --, 'd'],
1882 mask=[False, False, True, False],
1883 fill_value='N/A',
1884 dtype='<U1')
1886 Effect of the `copy` argument.
1888 >>> c = ma.masked_where(a <= 2, a)
1889 >>> c
1890 masked_array(data=[--, --, --, 3],
1891 mask=[ True, True, True, False],
1892 fill_value=999999)
1893 >>> c[0] = 99
1894 >>> c
1895 masked_array(data=[99, --, --, 3],
1896 mask=[False, True, True, False],
1897 fill_value=999999)
1898 >>> a
1899 array([0, 1, 2, 3])
1900 >>> c = ma.masked_where(a <= 2, a, copy=False)
1901 >>> c[0] = 99
1902 >>> c
1903 masked_array(data=[99, --, --, 3],
1904 mask=[False, True, True, False],
1905 fill_value=999999)
1906 >>> a
1907 array([99, 1, 2, 3])
1909 When `condition` or `a` contain masked values.
1911 >>> a = np.arange(4)
1912 >>> a = ma.masked_where(a == 2, a)
1913 >>> a
1914 masked_array(data=[0, 1, --, 3],
1915 mask=[False, False, True, False],
1916 fill_value=999999)
1917 >>> b = np.arange(4)
1918 >>> b = ma.masked_where(b == 0, b)
1919 >>> b
1920 masked_array(data=[--, 1, 2, 3],
1921 mask=[ True, False, False, False],
1922 fill_value=999999)
1923 >>> ma.masked_where(a == 3, b)
1924 masked_array(data=[--, 1, --, --],
1925 mask=[ True, False, True, True],
1926 fill_value=999999)
1928 """
1929 # Make sure that condition is a valid standard-type mask.
1930 cond = make_mask(condition, shrink=False)
1931 a = np.array(a, copy=copy, subok=True)
1933 (cshape, ashape) = (cond.shape, a.shape)
1934 if cshape and cshape != ashape:
1935 raise IndexError("Inconsistent shape between the condition and the input"
1936 " (got %s and %s)" % (cshape, ashape))
1937 if hasattr(a, '_mask'):
1938 cond = mask_or(cond, a._mask)
1939 cls = type(a)
1940 else:
1941 cls = MaskedArray
1942 result = a.view(cls)
1943 # Assign to *.mask so that structured masks are handled correctly.
1944 result.mask = _shrink_mask(cond)
1945 return result
1948def masked_greater(x, value, copy=True):
1949 """
1950 Mask an array where greater than a given value.
1952 This function is a shortcut to ``masked_where``, with
1953 `condition` = (x > value).
1955 See Also
1956 --------
1957 masked_where : Mask where a condition is met.
1959 Examples
1960 --------
1961 >>> import numpy.ma as ma
1962 >>> a = np.arange(4)
1963 >>> a
1964 array([0, 1, 2, 3])
1965 >>> ma.masked_greater(a, 2)
1966 masked_array(data=[0, 1, 2, --],
1967 mask=[False, False, False, True],
1968 fill_value=999999)
1970 """
1971 return masked_where(greater(x, value), x, copy=copy)
1974def masked_greater_equal(x, value, copy=True):
1975 """
1976 Mask an array where greater than or equal to a given value.
1978 This function is a shortcut to ``masked_where``, with
1979 `condition` = (x >= value).
1981 See Also
1982 --------
1983 masked_where : Mask where a condition is met.
1985 Examples
1986 --------
1987 >>> import numpy.ma as ma
1988 >>> a = np.arange(4)
1989 >>> a
1990 array([0, 1, 2, 3])
1991 >>> ma.masked_greater_equal(a, 2)
1992 masked_array(data=[0, 1, --, --],
1993 mask=[False, False, True, True],
1994 fill_value=999999)
1996 """
1997 return masked_where(greater_equal(x, value), x, copy=copy)
2000def masked_less(x, value, copy=True):
2001 """
2002 Mask an array where less than a given value.
2004 This function is a shortcut to ``masked_where``, with
2005 `condition` = (x < value).
2007 See Also
2008 --------
2009 masked_where : Mask where a condition is met.
2011 Examples
2012 --------
2013 >>> import numpy.ma as ma
2014 >>> a = np.arange(4)
2015 >>> a
2016 array([0, 1, 2, 3])
2017 >>> ma.masked_less(a, 2)
2018 masked_array(data=[--, --, 2, 3],
2019 mask=[ True, True, False, False],
2020 fill_value=999999)
2022 """
2023 return masked_where(less(x, value), x, copy=copy)
2026def masked_less_equal(x, value, copy=True):
2027 """
2028 Mask an array where less than or equal to a given value.
2030 This function is a shortcut to ``masked_where``, with
2031 `condition` = (x <= value).
2033 See Also
2034 --------
2035 masked_where : Mask where a condition is met.
2037 Examples
2038 --------
2039 >>> import numpy.ma as ma
2040 >>> a = np.arange(4)
2041 >>> a
2042 array([0, 1, 2, 3])
2043 >>> ma.masked_less_equal(a, 2)
2044 masked_array(data=[--, --, --, 3],
2045 mask=[ True, True, True, False],
2046 fill_value=999999)
2048 """
2049 return masked_where(less_equal(x, value), x, copy=copy)
2052def masked_not_equal(x, value, copy=True):
2053 """
2054 Mask an array where `not` equal to a given value.
2056 This function is a shortcut to ``masked_where``, with
2057 `condition` = (x != value).
2059 See Also
2060 --------
2061 masked_where : Mask where a condition is met.
2063 Examples
2064 --------
2065 >>> import numpy.ma as ma
2066 >>> a = np.arange(4)
2067 >>> a
2068 array([0, 1, 2, 3])
2069 >>> ma.masked_not_equal(a, 2)
2070 masked_array(data=[--, --, 2, --],
2071 mask=[ True, True, False, True],
2072 fill_value=999999)
2074 """
2075 return masked_where(not_equal(x, value), x, copy=copy)
2078def masked_equal(x, value, copy=True):
2079 """
2080 Mask an array where equal to a given value.
2082 This function is a shortcut to ``masked_where``, with
2083 `condition` = (x == value). For floating point arrays,
2084 consider using ``masked_values(x, value)``.
2086 See Also
2087 --------
2088 masked_where : Mask where a condition is met.
2089 masked_values : Mask using floating point equality.
2091 Examples
2092 --------
2093 >>> import numpy.ma as ma
2094 >>> a = np.arange(4)
2095 >>> a
2096 array([0, 1, 2, 3])
2097 >>> ma.masked_equal(a, 2)
2098 masked_array(data=[0, 1, --, 3],
2099 mask=[False, False, True, False],
2100 fill_value=2)
2102 """
2103 output = masked_where(equal(x, value), x, copy=copy)
2104 output.fill_value = value
2105 return output
2108def masked_inside(x, v1, v2, copy=True):
2109 """
2110 Mask an array inside a given interval.
2112 Shortcut to ``masked_where``, where `condition` is True for `x` inside
2113 the interval [v1,v2] (v1 <= x <= v2). The boundaries `v1` and `v2`
2114 can be given in either order.
2116 See Also
2117 --------
2118 masked_where : Mask where a condition is met.
2120 Notes
2121 -----
2122 The array `x` is prefilled with its filling value.
2124 Examples
2125 --------
2126 >>> import numpy.ma as ma
2127 >>> x = [0.31, 1.2, 0.01, 0.2, -0.4, -1.1]
2128 >>> ma.masked_inside(x, -0.3, 0.3)
2129 masked_array(data=[0.31, 1.2, --, --, -0.4, -1.1],
2130 mask=[False, False, True, True, False, False],
2131 fill_value=1e+20)
2133 The order of `v1` and `v2` doesn't matter.
2135 >>> ma.masked_inside(x, 0.3, -0.3)
2136 masked_array(data=[0.31, 1.2, --, --, -0.4, -1.1],
2137 mask=[False, False, True, True, False, False],
2138 fill_value=1e+20)
2140 """
2141 if v2 < v1:
2142 (v1, v2) = (v2, v1)
2143 xf = filled(x)
2144 condition = (xf >= v1) & (xf <= v2)
2145 return masked_where(condition, x, copy=copy)
2148def masked_outside(x, v1, v2, copy=True):
2149 """
2150 Mask an array outside a given interval.
2152 Shortcut to ``masked_where``, where `condition` is True for `x` outside
2153 the interval [v1,v2] (x < v1)|(x > v2).
2154 The boundaries `v1` and `v2` can be given in either order.
2156 See Also
2157 --------
2158 masked_where : Mask where a condition is met.
2160 Notes
2161 -----
2162 The array `x` is prefilled with its filling value.
2164 Examples
2165 --------
2166 >>> import numpy.ma as ma
2167 >>> x = [0.31, 1.2, 0.01, 0.2, -0.4, -1.1]
2168 >>> ma.masked_outside(x, -0.3, 0.3)
2169 masked_array(data=[--, --, 0.01, 0.2, --, --],
2170 mask=[ True, True, False, False, True, True],
2171 fill_value=1e+20)
2173 The order of `v1` and `v2` doesn't matter.
2175 >>> ma.masked_outside(x, 0.3, -0.3)
2176 masked_array(data=[--, --, 0.01, 0.2, --, --],
2177 mask=[ True, True, False, False, True, True],
2178 fill_value=1e+20)
2180 """
2181 if v2 < v1:
2182 (v1, v2) = (v2, v1)
2183 xf = filled(x)
2184 condition = (xf < v1) | (xf > v2)
2185 return masked_where(condition, x, copy=copy)
2188def masked_object(x, value, copy=True, shrink=True):
2189 """
2190 Mask the array `x` where the data are exactly equal to value.
2192 This function is similar to `masked_values`, but only suitable
2193 for object arrays: for floating point, use `masked_values` instead.
2195 Parameters
2196 ----------
2197 x : array_like
2198 Array to mask
2199 value : object
2200 Comparison value
2201 copy : {True, False}, optional
2202 Whether to return a copy of `x`.
2203 shrink : {True, False}, optional
2204 Whether to collapse a mask full of False to nomask
2206 Returns
2207 -------
2208 result : MaskedArray
2209 The result of masking `x` where equal to `value`.
2211 See Also
2212 --------
2213 masked_where : Mask where a condition is met.
2214 masked_equal : Mask where equal to a given value (integers).
2215 masked_values : Mask using floating point equality.
2217 Examples
2218 --------
2219 >>> import numpy.ma as ma
2220 >>> food = np.array(['green_eggs', 'ham'], dtype=object)
2221 >>> # don't eat spoiled food
2222 >>> eat = ma.masked_object(food, 'green_eggs')
2223 >>> eat
2224 masked_array(data=[--, 'ham'],
2225 mask=[ True, False],
2226 fill_value='green_eggs',
2227 dtype=object)
2228 >>> # plain ol` ham is boring
2229 >>> fresh_food = np.array(['cheese', 'ham', 'pineapple'], dtype=object)
2230 >>> eat = ma.masked_object(fresh_food, 'green_eggs')
2231 >>> eat
2232 masked_array(data=['cheese', 'ham', 'pineapple'],
2233 mask=False,
2234 fill_value='green_eggs',
2235 dtype=object)
2237 Note that `mask` is set to ``nomask`` if possible.
2239 >>> eat
2240 masked_array(data=['cheese', 'ham', 'pineapple'],
2241 mask=False,
2242 fill_value='green_eggs',
2243 dtype=object)
2245 """
2246 if isMaskedArray(x):
2247 condition = umath.equal(x._data, value)
2248 mask = x._mask
2249 else:
2250 condition = umath.equal(np.asarray(x), value)
2251 mask = nomask
2252 mask = mask_or(mask, make_mask(condition, shrink=shrink))
2253 return masked_array(x, mask=mask, copy=copy, fill_value=value)
2256def masked_values(x, value, rtol=1e-5, atol=1e-8, copy=True, shrink=True):
2257 """
2258 Mask using floating point equality.
2260 Return a MaskedArray, masked where the data in array `x` are approximately
2261 equal to `value`, determined using `isclose`. The default tolerances for
2262 `masked_values` are the same as those for `isclose`.
2264 For integer types, exact equality is used, in the same way as
2265 `masked_equal`.
2267 The fill_value is set to `value` and the mask is set to ``nomask`` if
2268 possible.
2270 Parameters
2271 ----------
2272 x : array_like
2273 Array to mask.
2274 value : float
2275 Masking value.
2276 rtol, atol : float, optional
2277 Tolerance parameters passed on to `isclose`
2278 copy : bool, optional
2279 Whether to return a copy of `x`.
2280 shrink : bool, optional
2281 Whether to collapse a mask full of False to ``nomask``.
2283 Returns
2284 -------
2285 result : MaskedArray
2286 The result of masking `x` where approximately equal to `value`.
2288 See Also
2289 --------
2290 masked_where : Mask where a condition is met.
2291 masked_equal : Mask where equal to a given value (integers).
2293 Examples
2294 --------
2295 >>> import numpy.ma as ma
2296 >>> x = np.array([1, 1.1, 2, 1.1, 3])
2297 >>> ma.masked_values(x, 1.1)
2298 masked_array(data=[1.0, --, 2.0, --, 3.0],
2299 mask=[False, True, False, True, False],
2300 fill_value=1.1)
2302 Note that `mask` is set to ``nomask`` if possible.
2304 >>> ma.masked_values(x, 1.5)
2305 masked_array(data=[1. , 1.1, 2. , 1.1, 3. ],
2306 mask=False,
2307 fill_value=1.5)
2309 For integers, the fill value will be different in general to the
2310 result of ``masked_equal``.
2312 >>> x = np.arange(5)
2313 >>> x
2314 array([0, 1, 2, 3, 4])
2315 >>> ma.masked_values(x, 2)
2316 masked_array(data=[0, 1, --, 3, 4],
2317 mask=[False, False, True, False, False],
2318 fill_value=2)
2319 >>> ma.masked_equal(x, 2)
2320 masked_array(data=[0, 1, --, 3, 4],
2321 mask=[False, False, True, False, False],
2322 fill_value=2)
2324 """
2325 xnew = filled(x, value)
2326 if np.issubdtype(xnew.dtype, np.floating):
2327 mask = np.isclose(xnew, value, atol=atol, rtol=rtol)
2328 else:
2329 mask = umath.equal(xnew, value)
2330 ret = masked_array(xnew, mask=mask, copy=copy, fill_value=value)
2331 if shrink:
2332 ret.shrink_mask()
2333 return ret
2336def masked_invalid(a, copy=True):
2337 """
2338 Mask an array where invalid values occur (NaNs or infs).
2340 This function is a shortcut to ``masked_where``, with
2341 `condition` = ~(np.isfinite(a)). Any pre-existing mask is conserved.
2342 Only applies to arrays with a dtype where NaNs or infs make sense
2343 (i.e. floating point types), but accepts any array_like object.
2345 See Also
2346 --------
2347 masked_where : Mask where a condition is met.
2349 Examples
2350 --------
2351 >>> import numpy.ma as ma
2352 >>> a = np.arange(5, dtype=float)
2353 >>> a[2] = np.NaN
2354 >>> a[3] = np.PINF
2355 >>> a
2356 array([ 0., 1., nan, inf, 4.])
2357 >>> ma.masked_invalid(a)
2358 masked_array(data=[0.0, 1.0, --, --, 4.0],
2359 mask=[False, False, True, True, False],
2360 fill_value=1e+20)
2362 """
2363 a = np.array(a, copy=copy, subok=True)
2364 mask = getattr(a, '_mask', None)
2365 if mask is not None:
2366 condition = ~(np.isfinite(getdata(a)))
2367 if mask is not nomask:
2368 condition |= mask
2369 cls = type(a)
2370 else:
2371 condition = ~(np.isfinite(a))
2372 cls = MaskedArray
2373 result = a.view(cls)
2374 result._mask = condition
2375 return result
2378###############################################################################
2379# Printing options #
2380###############################################################################
2383class _MaskedPrintOption:
2384 """
2385 Handle the string used to represent missing data in a masked array.
2387 """
2389 def __init__(self, display):
2390 """
2391 Create the masked_print_option object.
2393 """
2394 self._display = display
2395 self._enabled = True
2397 def display(self):
2398 """
2399 Display the string to print for masked values.
2401 """
2402 return self._display
2404 def set_display(self, s):
2405 """
2406 Set the string to print for masked values.
2408 """
2409 self._display = s
2411 def enabled(self):
2412 """
2413 Is the use of the display value enabled?
2415 """
2416 return self._enabled
2418 def enable(self, shrink=1):
2419 """
2420 Set the enabling shrink to `shrink`.
2422 """
2423 self._enabled = shrink
2425 def __str__(self):
2426 return str(self._display)
2428 __repr__ = __str__
2430# if you single index into a masked location you get this object.
2431masked_print_option = _MaskedPrintOption('--')
2434def _recursive_printoption(result, mask, printopt):
2435 """
2436 Puts printoptions in result where mask is True.
2438 Private function allowing for recursion
2440 """
2441 names = result.dtype.names
2442 if names is not None:
2443 for name in names:
2444 curdata = result[name]
2445 curmask = mask[name]
2446 _recursive_printoption(curdata, curmask, printopt)
2447 else:
2448 np.copyto(result, printopt, where=mask)
2449 return
2451# For better or worse, these end in a newline
2452_legacy_print_templates = dict(
2453 long_std=textwrap.dedent("""\
2454 masked_%(name)s(data =
2455 %(data)s,
2456 %(nlen)s mask =
2457 %(mask)s,
2458 %(nlen)s fill_value = %(fill)s)
2459 """),
2460 long_flx=textwrap.dedent("""\
2461 masked_%(name)s(data =
2462 %(data)s,
2463 %(nlen)s mask =
2464 %(mask)s,
2465 %(nlen)s fill_value = %(fill)s,
2466 %(nlen)s dtype = %(dtype)s)
2467 """),
2468 short_std=textwrap.dedent("""\
2469 masked_%(name)s(data = %(data)s,
2470 %(nlen)s mask = %(mask)s,
2471 %(nlen)s fill_value = %(fill)s)
2472 """),
2473 short_flx=textwrap.dedent("""\
2474 masked_%(name)s(data = %(data)s,
2475 %(nlen)s mask = %(mask)s,
2476 %(nlen)s fill_value = %(fill)s,
2477 %(nlen)s dtype = %(dtype)s)
2478 """)
2479)
2481###############################################################################
2482# MaskedArray class #
2483###############################################################################
2486def _recursive_filled(a, mask, fill_value):
2487 """
2488 Recursively fill `a` with `fill_value`.
2490 """
2491 names = a.dtype.names
2492 for name in names:
2493 current = a[name]
2494 if current.dtype.names is not None:
2495 _recursive_filled(current, mask[name], fill_value[name])
2496 else:
2497 np.copyto(current, fill_value[name], where=mask[name])
2500def flatten_structured_array(a):
2501 """
2502 Flatten a structured array.
2504 The data type of the output is chosen such that it can represent all of the
2505 (nested) fields.
2507 Parameters
2508 ----------
2509 a : structured array
2511 Returns
2512 -------
2513 output : masked array or ndarray
2514 A flattened masked array if the input is a masked array, otherwise a
2515 standard ndarray.
2517 Examples
2518 --------
2519 >>> ndtype = [('a', int), ('b', float)]
2520 >>> a = np.array([(1, 1), (2, 2)], dtype=ndtype)
2521 >>> np.ma.flatten_structured_array(a)
2522 array([[1., 1.],
2523 [2., 2.]])
2525 """
2527 def flatten_sequence(iterable):
2528 """
2529 Flattens a compound of nested iterables.
2531 """
2532 for elm in iter(iterable):
2533 if hasattr(elm, '__iter__'):
2534 yield from flatten_sequence(elm)
2535 else:
2536 yield elm
2538 a = np.asanyarray(a)
2539 inishape = a.shape
2540 a = a.ravel()
2541 if isinstance(a, MaskedArray):
2542 out = np.array([tuple(flatten_sequence(d.item())) for d in a._data])
2543 out = out.view(MaskedArray)
2544 out._mask = np.array([tuple(flatten_sequence(d.item()))
2545 for d in getmaskarray(a)])
2546 else:
2547 out = np.array([tuple(flatten_sequence(d.item())) for d in a])
2548 if len(inishape) > 1:
2549 newshape = list(out.shape)
2550 newshape[0] = inishape
2551 out.shape = tuple(flatten_sequence(newshape))
2552 return out
2555def _arraymethod(funcname, onmask=True):
2556 """
2557 Return a class method wrapper around a basic array method.
2559 Creates a class method which returns a masked array, where the new
2560 ``_data`` array is the output of the corresponding basic method called
2561 on the original ``_data``.
2563 If `onmask` is True, the new mask is the output of the method called
2564 on the initial mask. Otherwise, the new mask is just a reference
2565 to the initial mask.
2567 Parameters
2568 ----------
2569 funcname : str
2570 Name of the function to apply on data.
2571 onmask : bool
2572 Whether the mask must be processed also (True) or left
2573 alone (False). Default is True. Make available as `_onmask`
2574 attribute.
2576 Returns
2577 -------
2578 method : instancemethod
2579 Class method wrapper of the specified basic array method.
2581 """
2582 def wrapped_method(self, *args, **params):
2583 result = getattr(self._data, funcname)(*args, **params)
2584 result = result.view(type(self))
2585 result._update_from(self)
2586 mask = self._mask
2587 if not onmask:
2588 result.__setmask__(mask)
2589 elif mask is not nomask:
2590 # __setmask__ makes a copy, which we don't want
2591 result._mask = getattr(mask, funcname)(*args, **params)
2592 return result
2593 methdoc = getattr(ndarray, funcname, None) or getattr(np, funcname, None)
2594 if methdoc is not None:
2595 wrapped_method.__doc__ = methdoc.__doc__
2596 wrapped_method.__name__ = funcname
2597 return wrapped_method
2600class MaskedIterator:
2601 """
2602 Flat iterator object to iterate over masked arrays.
2604 A `MaskedIterator` iterator is returned by ``x.flat`` for any masked array
2605 `x`. It allows iterating over the array as if it were a 1-D array,
2606 either in a for-loop or by calling its `next` method.
2608 Iteration is done in C-contiguous style, with the last index varying the
2609 fastest. The iterator can also be indexed using basic slicing or
2610 advanced indexing.
2612 See Also
2613 --------
2614 MaskedArray.flat : Return a flat iterator over an array.
2615 MaskedArray.flatten : Returns a flattened copy of an array.
2617 Notes
2618 -----
2619 `MaskedIterator` is not exported by the `ma` module. Instead of
2620 instantiating a `MaskedIterator` directly, use `MaskedArray.flat`.
2622 Examples
2623 --------
2624 >>> x = np.ma.array(arange(6).reshape(2, 3))
2625 >>> fl = x.flat
2626 >>> type(fl)
2627 <class 'numpy.ma.core.MaskedIterator'>
2628 >>> for item in fl:
2629 ... print(item)
2630 ...
2631 0
2632 1
2633 2
2634 3
2635 4
2636 5
2638 Extracting more than a single element b indexing the `MaskedIterator`
2639 returns a masked array:
2641 >>> fl[2:4]
2642 masked_array(data = [2 3],
2643 mask = False,
2644 fill_value = 999999)
2646 """
2648 def __init__(self, ma):
2649 self.ma = ma
2650 self.dataiter = ma._data.flat
2652 if ma._mask is nomask:
2653 self.maskiter = None
2654 else:
2655 self.maskiter = ma._mask.flat
2657 def __iter__(self):
2658 return self
2660 def __getitem__(self, indx):
2661 result = self.dataiter.__getitem__(indx).view(type(self.ma))
2662 if self.maskiter is not None:
2663 _mask = self.maskiter.__getitem__(indx)
2664 if isinstance(_mask, ndarray):
2665 # set shape to match that of data; this is needed for matrices
2666 _mask.shape = result.shape
2667 result._mask = _mask
2668 elif isinstance(_mask, np.void):
2669 return mvoid(result, mask=_mask, hardmask=self.ma._hardmask)
2670 elif _mask: # Just a scalar, masked
2671 return masked
2672 return result
2674 # This won't work if ravel makes a copy
2675 def __setitem__(self, index, value):
2676 self.dataiter[index] = getdata(value)
2677 if self.maskiter is not None:
2678 self.maskiter[index] = getmaskarray(value)
2680 def __next__(self):
2681 """
2682 Return the next value, or raise StopIteration.
2684 Examples
2685 --------
2686 >>> x = np.ma.array([3, 2], mask=[0, 1])
2687 >>> fl = x.flat
2688 >>> next(fl)
2689 3
2690 >>> next(fl)
2691 masked
2692 >>> next(fl)
2693 Traceback (most recent call last):
2694 ...
2695 StopIteration
2697 """
2698 d = next(self.dataiter)
2699 if self.maskiter is not None:
2700 m = next(self.maskiter)
2701 if isinstance(m, np.void):
2702 return mvoid(d, mask=m, hardmask=self.ma._hardmask)
2703 elif m: # Just a scalar, masked
2704 return masked
2705 return d
2708class MaskedArray(ndarray):
2709 """
2710 An array class with possibly masked values.
2712 Masked values of True exclude the corresponding element from any
2713 computation.
2715 Construction::
2717 x = MaskedArray(data, mask=nomask, dtype=None, copy=False, subok=True,
2718 ndmin=0, fill_value=None, keep_mask=True, hard_mask=None,
2719 shrink=True, order=None)
2721 Parameters
2722 ----------
2723 data : array_like
2724 Input data.
2725 mask : sequence, optional
2726 Mask. Must be convertible to an array of booleans with the same
2727 shape as `data`. True indicates a masked (i.e. invalid) data.
2728 dtype : dtype, optional
2729 Data type of the output.
2730 If `dtype` is None, the type of the data argument (``data.dtype``)
2731 is used. If `dtype` is not None and different from ``data.dtype``,
2732 a copy is performed.
2733 copy : bool, optional
2734 Whether to copy the input data (True), or to use a reference instead.
2735 Default is False.
2736 subok : bool, optional
2737 Whether to return a subclass of `MaskedArray` if possible (True) or a
2738 plain `MaskedArray`. Default is True.
2739 ndmin : int, optional
2740 Minimum number of dimensions. Default is 0.
2741 fill_value : scalar, optional
2742 Value used to fill in the masked values when necessary.
2743 If None, a default based on the data-type is used.
2744 keep_mask : bool, optional
2745 Whether to combine `mask` with the mask of the input data, if any
2746 (True), or to use only `mask` for the output (False). Default is True.
2747 hard_mask : bool, optional
2748 Whether to use a hard mask or not. With a hard mask, masked values
2749 cannot be unmasked. Default is False.
2750 shrink : bool, optional
2751 Whether to force compression of an empty mask. Default is True.
2752 order : {'C', 'F', 'A'}, optional
2753 Specify the order of the array. If order is 'C', then the array
2754 will be in C-contiguous order (last-index varies the fastest).
2755 If order is 'F', then the returned array will be in
2756 Fortran-contiguous order (first-index varies the fastest).
2757 If order is 'A' (default), then the returned array may be
2758 in any order (either C-, Fortran-contiguous, or even discontiguous),
2759 unless a copy is required, in which case it will be C-contiguous.
2761 Examples
2762 --------
2764 The ``mask`` can be initialized with an array of boolean values
2765 with the same shape as ``data``.
2767 >>> data = np.arange(6).reshape((2, 3))
2768 >>> np.ma.MaskedArray(data, mask=[[False, True, False],
2769 ... [False, False, True]])
2770 masked_array(
2771 data=[[0, --, 2],
2772 [3, 4, --]],
2773 mask=[[False, True, False],
2774 [False, False, True]],
2775 fill_value=999999)
2777 Alternatively, the ``mask`` can be initialized to homogeneous boolean
2778 array with the same shape as ``data`` by passing in a scalar
2779 boolean value:
2781 >>> np.ma.MaskedArray(data, mask=False)
2782 masked_array(
2783 data=[[0, 1, 2],
2784 [3, 4, 5]],
2785 mask=[[False, False, False],
2786 [False, False, False]],
2787 fill_value=999999)
2789 >>> np.ma.MaskedArray(data, mask=True)
2790 masked_array(
2791 data=[[--, --, --],
2792 [--, --, --]],
2793 mask=[[ True, True, True],
2794 [ True, True, True]],
2795 fill_value=999999,
2796 dtype=int64)
2798 .. note::
2799 The recommended practice for initializing ``mask`` with a scalar
2800 boolean value is to use ``True``/``False`` rather than
2801 ``np.True_``/``np.False_``. The reason is :attr:`nomask`
2802 is represented internally as ``np.False_``.
2804 >>> np.False_ is np.ma.nomask
2805 True
2807 """
2809 __array_priority__ = 15
2810 _defaultmask = nomask
2811 _defaulthardmask = False
2812 _baseclass = ndarray
2814 # Maximum number of elements per axis used when printing an array. The
2815 # 1d case is handled separately because we need more values in this case.
2816 _print_width = 100
2817 _print_width_1d = 1500
2819 def __new__(cls, data=None, mask=nomask, dtype=None, copy=False,
2820 subok=True, ndmin=0, fill_value=None, keep_mask=True,
2821 hard_mask=None, shrink=True, order=None, **options):
2822 """
2823 Create a new masked array from scratch.
2825 Notes
2826 -----
2827 A masked array can also be created by taking a .view(MaskedArray).
2829 """
2830 # Process data.
2831 _data = np.array(data, dtype=dtype, copy=copy,
2832 order=order, subok=True, ndmin=ndmin)
2833 _baseclass = getattr(data, '_baseclass', type(_data))
2834 # Check that we're not erasing the mask.
2835 if isinstance(data, MaskedArray) and (data.shape != _data.shape):
2836 copy = True
2838 # Here, we copy the _view_, so that we can attach new properties to it
2839 # we must never do .view(MaskedConstant), as that would create a new
2840 # instance of np.ma.masked, which make identity comparison fail
2841 if isinstance(data, cls) and subok and not isinstance(data, MaskedConstant):
2842 _data = ndarray.view(_data, type(data))
2843 else:
2844 _data = ndarray.view(_data, cls)
2845 # Backwards compatibility w/ numpy.core.ma.
2846 if hasattr(data, '_mask') and not isinstance(data, ndarray):
2847 _data._mask = data._mask
2848 # FIXME _sharedmask is never used.
2849 _sharedmask = True
2850 # Process mask.
2851 # Type of the mask
2852 mdtype = make_mask_descr(_data.dtype)
2854 if mask is nomask:
2855 # Case 1. : no mask in input.
2856 # Erase the current mask ?
2857 if not keep_mask:
2858 # With a reduced version
2859 if shrink:
2860 _data._mask = nomask
2861 # With full version
2862 else:
2863 _data._mask = np.zeros(_data.shape, dtype=mdtype)
2864 # Check whether we missed something
2865 elif isinstance(data, (tuple, list)):
2866 try:
2867 # If data is a sequence of masked array
2868 mask = np.array([getmaskarray(np.asanyarray(m, dtype=mdtype))
2869 for m in data], dtype=mdtype)
2870 except ValueError:
2871 # If data is nested
2872 mask = nomask
2873 # Force shrinking of the mask if needed (and possible)
2874 if (mdtype == MaskType) and mask.any():
2875 _data._mask = mask
2876 _data._sharedmask = False
2877 else:
2878 _data._sharedmask = not copy
2879 if copy:
2880 _data._mask = _data._mask.copy()
2881 # Reset the shape of the original mask
2882 if getmask(data) is not nomask:
2883 data._mask.shape = data.shape
2884 else:
2885 # Case 2. : With a mask in input.
2886 # If mask is boolean, create an array of True or False
2887 if mask is True and mdtype == MaskType:
2888 mask = np.ones(_data.shape, dtype=mdtype)
2889 elif mask is False and mdtype == MaskType:
2890 mask = np.zeros(_data.shape, dtype=mdtype)
2891 else:
2892 # Read the mask with the current mdtype
2893 try:
2894 mask = np.array(mask, copy=copy, dtype=mdtype)
2895 # Or assume it's a sequence of bool/int
2896 except TypeError:
2897 mask = np.array([tuple([m] * len(mdtype)) for m in mask],
2898 dtype=mdtype)
2899 # Make sure the mask and the data have the same shape
2900 if mask.shape != _data.shape:
2901 (nd, nm) = (_data.size, mask.size)
2902 if nm == 1:
2903 mask = np.resize(mask, _data.shape)
2904 elif nm == nd:
2905 mask = np.reshape(mask, _data.shape)
2906 else:
2907 msg = "Mask and data not compatible: data size is %i, " + \
2908 "mask size is %i."
2909 raise MaskError(msg % (nd, nm))
2910 copy = True
2911 # Set the mask to the new value
2912 if _data._mask is nomask:
2913 _data._mask = mask
2914 _data._sharedmask = not copy
2915 else:
2916 if not keep_mask:
2917 _data._mask = mask
2918 _data._sharedmask = not copy
2919 else:
2920 if _data.dtype.names is not None:
2921 def _recursive_or(a, b):
2922 "do a|=b on each field of a, recursively"
2923 for name in a.dtype.names:
2924 (af, bf) = (a[name], b[name])
2925 if af.dtype.names is not None:
2926 _recursive_or(af, bf)
2927 else:
2928 af |= bf
2930 _recursive_or(_data._mask, mask)
2931 else:
2932 _data._mask = np.logical_or(mask, _data._mask)
2933 _data._sharedmask = False
2934 # Update fill_value.
2935 if fill_value is None:
2936 fill_value = getattr(data, '_fill_value', None)
2937 # But don't run the check unless we have something to check.
2938 if fill_value is not None:
2939 _data._fill_value = _check_fill_value(fill_value, _data.dtype)
2940 # Process extra options ..
2941 if hard_mask is None:
2942 _data._hardmask = getattr(data, '_hardmask', False)
2943 else:
2944 _data._hardmask = hard_mask
2945 _data._baseclass = _baseclass
2946 return _data
2949 def _update_from(self, obj):
2950 """
2951 Copies some attributes of obj to self.
2953 """
2954 if isinstance(obj, ndarray):
2955 _baseclass = type(obj)
2956 else:
2957 _baseclass = ndarray
2958 # We need to copy the _basedict to avoid backward propagation
2959 _optinfo = {}
2960 _optinfo.update(getattr(obj, '_optinfo', {}))
2961 _optinfo.update(getattr(obj, '_basedict', {}))
2962 if not isinstance(obj, MaskedArray):
2963 _optinfo.update(getattr(obj, '__dict__', {}))
2964 _dict = dict(_fill_value=getattr(obj, '_fill_value', None),
2965 _hardmask=getattr(obj, '_hardmask', False),
2966 _sharedmask=getattr(obj, '_sharedmask', False),
2967 _isfield=getattr(obj, '_isfield', False),
2968 _baseclass=getattr(obj, '_baseclass', _baseclass),
2969 _optinfo=_optinfo,
2970 _basedict=_optinfo)
2971 self.__dict__.update(_dict)
2972 self.__dict__.update(_optinfo)
2973 return
2975 def __array_finalize__(self, obj):
2976 """
2977 Finalizes the masked array.
2979 """
2980 # Get main attributes.
2981 self._update_from(obj)
2983 # We have to decide how to initialize self.mask, based on
2984 # obj.mask. This is very difficult. There might be some
2985 # correspondence between the elements in the array we are being
2986 # created from (= obj) and us. Or there might not. This method can
2987 # be called in all kinds of places for all kinds of reasons -- could
2988 # be empty_like, could be slicing, could be a ufunc, could be a view.
2989 # The numpy subclassing interface simply doesn't give us any way
2990 # to know, which means that at best this method will be based on
2991 # guesswork and heuristics. To make things worse, there isn't even any
2992 # clear consensus about what the desired behavior is. For instance,
2993 # most users think that np.empty_like(marr) -- which goes via this
2994 # method -- should return a masked array with an empty mask (see
2995 # gh-3404 and linked discussions), but others disagree, and they have
2996 # existing code which depends on empty_like returning an array that
2997 # matches the input mask.
2998 #
2999 # Historically our algorithm was: if the template object mask had the
3000 # same *number of elements* as us, then we used *it's mask object
3001 # itself* as our mask, so that writes to us would also write to the
3002 # original array. This is horribly broken in multiple ways.
3003 #
3004 # Now what we do instead is, if the template object mask has the same
3005 # number of elements as us, and we do not have the same base pointer
3006 # as the template object (b/c views like arr[...] should keep the same
3007 # mask), then we make a copy of the template object mask and use
3008 # that. This is also horribly broken but somewhat less so. Maybe.
3009 if isinstance(obj, ndarray):
3010 # XX: This looks like a bug -- shouldn't it check self.dtype
3011 # instead?
3012 if obj.dtype.names is not None:
3013 _mask = getmaskarray(obj)
3014 else:
3015 _mask = getmask(obj)
3017 # If self and obj point to exactly the same data, then probably
3018 # self is a simple view of obj (e.g., self = obj[...]), so they
3019 # should share the same mask. (This isn't 100% reliable, e.g. self
3020 # could be the first row of obj, or have strange strides, but as a
3021 # heuristic it's not bad.) In all other cases, we make a copy of
3022 # the mask, so that future modifications to 'self' do not end up
3023 # side-effecting 'obj' as well.
3024 if (_mask is not nomask and obj.__array_interface__["data"][0]
3025 != self.__array_interface__["data"][0]):
3026 # We should make a copy. But we could get here via astype,
3027 # in which case the mask might need a new dtype as well
3028 # (e.g., changing to or from a structured dtype), and the
3029 # order could have changed. So, change the mask type if
3030 # needed and use astype instead of copy.
3031 if self.dtype == obj.dtype:
3032 _mask_dtype = _mask.dtype
3033 else:
3034 _mask_dtype = make_mask_descr(self.dtype)
3036 if self.flags.c_contiguous:
3037 order = "C"
3038 elif self.flags.f_contiguous:
3039 order = "F"
3040 else:
3041 order = "K"
3043 _mask = _mask.astype(_mask_dtype, order)
3044 else:
3045 # Take a view so shape changes, etc., do not propagate back.
3046 _mask = _mask.view()
3047 else:
3048 _mask = nomask
3050 self._mask = _mask
3051 # Finalize the mask
3052 if self._mask is not nomask:
3053 try:
3054 self._mask.shape = self.shape
3055 except ValueError:
3056 self._mask = nomask
3057 except (TypeError, AttributeError):
3058 # When _mask.shape is not writable (because it's a void)
3059 pass
3061 # Finalize the fill_value
3062 if self._fill_value is not None:
3063 self._fill_value = _check_fill_value(self._fill_value, self.dtype)
3064 elif self.dtype.names is not None:
3065 # Finalize the default fill_value for structured arrays
3066 self._fill_value = _check_fill_value(None, self.dtype)
3068 def __array_wrap__(self, obj, context=None):
3069 """
3070 Special hook for ufuncs.
3072 Wraps the numpy array and sets the mask according to context.
3074 """
3075 if obj is self: # for in-place operations
3076 result = obj
3077 else:
3078 result = obj.view(type(self))
3079 result._update_from(self)
3081 if context is not None:
3082 result._mask = result._mask.copy()
3083 func, args, out_i = context
3084 # args sometimes contains outputs (gh-10459), which we don't want
3085 input_args = args[:func.nin]
3086 m = reduce(mask_or, [getmaskarray(arg) for arg in input_args])
3087 # Get the domain mask
3088 domain = ufunc_domain.get(func, None)
3089 if domain is not None:
3090 # Take the domain, and make sure it's a ndarray
3091 with np.errstate(divide='ignore', invalid='ignore'):
3092 d = filled(domain(*input_args), True)
3094 if d.any():
3095 # Fill the result where the domain is wrong
3096 try:
3097 # Binary domain: take the last value
3098 fill_value = ufunc_fills[func][-1]
3099 except TypeError:
3100 # Unary domain: just use this one
3101 fill_value = ufunc_fills[func]
3102 except KeyError:
3103 # Domain not recognized, use fill_value instead
3104 fill_value = self.fill_value
3106 np.copyto(result, fill_value, where=d)
3108 # Update the mask
3109 if m is nomask:
3110 m = d
3111 else:
3112 # Don't modify inplace, we risk back-propagation
3113 m = (m | d)
3115 # Make sure the mask has the proper size
3116 if result is not self and result.shape == () and m:
3117 return masked
3118 else:
3119 result._mask = m
3120 result._sharedmask = False
3122 return result
3124 def view(self, dtype=None, type=None, fill_value=None):
3125 """
3126 Return a view of the MaskedArray data.
3128 Parameters
3129 ----------
3130 dtype : data-type or ndarray sub-class, optional
3131 Data-type descriptor of the returned view, e.g., float32 or int16.
3132 The default, None, results in the view having the same data-type
3133 as `a`. As with ``ndarray.view``, dtype can also be specified as
3134 an ndarray sub-class, which then specifies the type of the
3135 returned object (this is equivalent to setting the ``type``
3136 parameter).
3137 type : Python type, optional
3138 Type of the returned view, either ndarray or a subclass. The
3139 default None results in type preservation.
3140 fill_value : scalar, optional
3141 The value to use for invalid entries (None by default).
3142 If None, then this argument is inferred from the passed `dtype`, or
3143 in its absence the original array, as discussed in the notes below.
3145 See Also
3146 --------
3147 numpy.ndarray.view : Equivalent method on ndarray object.
3149 Notes
3150 -----
3152 ``a.view()`` is used two different ways:
3154 ``a.view(some_dtype)`` or ``a.view(dtype=some_dtype)`` constructs a view
3155 of the array's memory with a different data-type. This can cause a
3156 reinterpretation of the bytes of memory.
3158 ``a.view(ndarray_subclass)`` or ``a.view(type=ndarray_subclass)`` just
3159 returns an instance of `ndarray_subclass` that looks at the same array
3160 (same shape, dtype, etc.) This does not cause a reinterpretation of the
3161 memory.
3163 If `fill_value` is not specified, but `dtype` is specified (and is not
3164 an ndarray sub-class), the `fill_value` of the MaskedArray will be
3165 reset. If neither `fill_value` nor `dtype` are specified (or if
3166 `dtype` is an ndarray sub-class), then the fill value is preserved.
3167 Finally, if `fill_value` is specified, but `dtype` is not, the fill
3168 value is set to the specified value.
3170 For ``a.view(some_dtype)``, if ``some_dtype`` has a different number of
3171 bytes per entry than the previous dtype (for example, converting a
3172 regular array to a structured array), then the behavior of the view
3173 cannot be predicted just from the superficial appearance of ``a`` (shown
3174 by ``print(a)``). It also depends on exactly how ``a`` is stored in
3175 memory. Therefore if ``a`` is C-ordered versus fortran-ordered, versus
3176 defined as a slice or transpose, etc., the view may give different
3177 results.
3178 """
3180 if dtype is None:
3181 if type is None:
3182 output = ndarray.view(self)
3183 else:
3184 output = ndarray.view(self, type)
3185 elif type is None:
3186 try:
3187 if issubclass(dtype, ndarray):
3188 output = ndarray.view(self, dtype)
3189 dtype = None
3190 else:
3191 output = ndarray.view(self, dtype)
3192 except TypeError:
3193 output = ndarray.view(self, dtype)
3194 else:
3195 output = ndarray.view(self, dtype, type)
3197 # also make the mask be a view (so attr changes to the view's
3198 # mask do no affect original object's mask)
3199 # (especially important to avoid affecting np.masked singleton)
3200 if getmask(output) is not nomask:
3201 output._mask = output._mask.view()
3203 # Make sure to reset the _fill_value if needed
3204 if getattr(output, '_fill_value', None) is not None:
3205 if fill_value is None:
3206 if dtype is None:
3207 pass # leave _fill_value as is
3208 else:
3209 output._fill_value = None
3210 else:
3211 output.fill_value = fill_value
3212 return output
3214 def __getitem__(self, indx):
3215 """
3216 x.__getitem__(y) <==> x[y]
3218 Return the item described by i, as a masked array.
3220 """
3221 # We could directly use ndarray.__getitem__ on self.
3222 # But then we would have to modify __array_finalize__ to prevent the
3223 # mask of being reshaped if it hasn't been set up properly yet
3224 # So it's easier to stick to the current version
3225 dout = self.data[indx]
3226 _mask = self._mask
3228 def _is_scalar(m):
3229 return not isinstance(m, np.ndarray)
3231 def _scalar_heuristic(arr, elem):
3232 """
3233 Return whether `elem` is a scalar result of indexing `arr`, or None
3234 if undecidable without promoting nomask to a full mask
3235 """
3236 # obviously a scalar
3237 if not isinstance(elem, np.ndarray):
3238 return True
3240 # object array scalar indexing can return anything
3241 elif arr.dtype.type is np.object_:
3242 if arr.dtype is not elem.dtype:
3243 # elem is an array, but dtypes do not match, so must be
3244 # an element
3245 return True
3247 # well-behaved subclass that only returns 0d arrays when
3248 # expected - this is not a scalar
3249 elif type(arr).__getitem__ == ndarray.__getitem__:
3250 return False
3252 return None
3254 if _mask is not nomask:
3255 # _mask cannot be a subclass, so it tells us whether we should
3256 # expect a scalar. It also cannot be of dtype object.
3257 mout = _mask[indx]
3258 scalar_expected = _is_scalar(mout)
3260 else:
3261 # attempt to apply the heuristic to avoid constructing a full mask
3262 mout = nomask
3263 scalar_expected = _scalar_heuristic(self.data, dout)
3264 if scalar_expected is None:
3265 # heuristics have failed
3266 # construct a full array, so we can be certain. This is costly.
3267 # we could also fall back on ndarray.__getitem__(self.data, indx)
3268 scalar_expected = _is_scalar(getmaskarray(self)[indx])
3270 # Did we extract a single item?
3271 if scalar_expected:
3272 # A record
3273 if isinstance(dout, np.void):
3274 # We should always re-cast to mvoid, otherwise users can
3275 # change masks on rows that already have masked values, but not
3276 # on rows that have no masked values, which is inconsistent.
3277 return mvoid(dout, mask=mout, hardmask=self._hardmask)
3279 # special case introduced in gh-5962
3280 elif (self.dtype.type is np.object_ and
3281 isinstance(dout, np.ndarray) and
3282 dout is not masked):
3283 # If masked, turn into a MaskedArray, with everything masked.
3284 if mout:
3285 return MaskedArray(dout, mask=True)
3286 else:
3287 return dout
3289 # Just a scalar
3290 else:
3291 if mout:
3292 return masked
3293 else:
3294 return dout
3295 else:
3296 # Force dout to MA
3297 dout = dout.view(type(self))
3298 # Inherit attributes from self
3299 dout._update_from(self)
3300 # Check the fill_value
3301 if is_string_or_list_of_strings(indx):
3302 if self._fill_value is not None:
3303 dout._fill_value = self._fill_value[indx]
3305 # Something like gh-15895 has happened if this check fails.
3306 # _fill_value should always be an ndarray.
3307 if not isinstance(dout._fill_value, np.ndarray):
3308 raise RuntimeError('Internal NumPy error.')
3309 # If we're indexing a multidimensional field in a
3310 # structured array (such as dtype("(2,)i2,(2,)i1")),
3311 # dimensionality goes up (M[field].ndim == M.ndim +
3312 # M.dtype[field].ndim). That's fine for
3313 # M[field] but problematic for M[field].fill_value
3314 # which should have shape () to avoid breaking several
3315 # methods. There is no great way out, so set to
3316 # first element. See issue #6723.
3317 if dout._fill_value.ndim > 0:
3318 if not (dout._fill_value ==
3319 dout._fill_value.flat[0]).all():
3320 warnings.warn(
3321 "Upon accessing multidimensional field "
3322 f"{indx!s}, need to keep dimensionality "
3323 "of fill_value at 0. Discarding "
3324 "heterogeneous fill_value and setting "
3325 f"all to {dout._fill_value[0]!s}.",
3326 stacklevel=2)
3327 # Need to use `.flat[0:1].squeeze(...)` instead of just
3328 # `.flat[0]` to ensure the result is a 0d array and not
3329 # a scalar.
3330 dout._fill_value = dout._fill_value.flat[0:1].squeeze(axis=0)
3331 dout._isfield = True
3332 # Update the mask if needed
3333 if mout is not nomask:
3334 # set shape to match that of data; this is needed for matrices
3335 dout._mask = reshape(mout, dout.shape)
3336 dout._sharedmask = True
3337 # Note: Don't try to check for m.any(), that'll take too long
3338 return dout
3340 def __setitem__(self, indx, value):
3341 """
3342 x.__setitem__(i, y) <==> x[i]=y
3344 Set item described by index. If value is masked, masks those
3345 locations.
3347 """
3348 if self is masked:
3349 raise MaskError('Cannot alter the masked element.')
3350 _data = self._data
3351 _mask = self._mask
3352 if isinstance(indx, str):
3353 _data[indx] = value
3354 if _mask is nomask:
3355 self._mask = _mask = make_mask_none(self.shape, self.dtype)
3356 _mask[indx] = getmask(value)
3357 return
3359 _dtype = _data.dtype
3361 if value is masked:
3362 # The mask wasn't set: create a full version.
3363 if _mask is nomask:
3364 _mask = self._mask = make_mask_none(self.shape, _dtype)
3365 # Now, set the mask to its value.
3366 if _dtype.names is not None:
3367 _mask[indx] = tuple([True] * len(_dtype.names))
3368 else:
3369 _mask[indx] = True
3370 return
3372 # Get the _data part of the new value
3373 dval = getattr(value, '_data', value)
3374 # Get the _mask part of the new value
3375 mval = getmask(value)
3376 if _dtype.names is not None and mval is nomask:
3377 mval = tuple([False] * len(_dtype.names))
3378 if _mask is nomask:
3379 # Set the data, then the mask
3380 _data[indx] = dval
3381 if mval is not nomask:
3382 _mask = self._mask = make_mask_none(self.shape, _dtype)
3383 _mask[indx] = mval
3384 elif not self._hardmask:
3385 # Set the data, then the mask
3386 _data[indx] = dval
3387 _mask[indx] = mval
3388 elif hasattr(indx, 'dtype') and (indx.dtype == MaskType):
3389 indx = indx * umath.logical_not(_mask)
3390 _data[indx] = dval
3391 else:
3392 if _dtype.names is not None:
3393 err_msg = "Flexible 'hard' masks are not yet supported."
3394 raise NotImplementedError(err_msg)
3395 mindx = mask_or(_mask[indx], mval, copy=True)
3396 dindx = self._data[indx]
3397 if dindx.size > 1:
3398 np.copyto(dindx, dval, where=~mindx)
3399 elif mindx is nomask:
3400 dindx = dval
3401 _data[indx] = dindx
3402 _mask[indx] = mindx
3403 return
3405 # Define so that we can overwrite the setter.
3406 @property
3407 def dtype(self):
3408 return super(MaskedArray, self).dtype
3410 @dtype.setter
3411 def dtype(self, dtype):
3412 super(MaskedArray, type(self)).dtype.__set__(self, dtype)
3413 if self._mask is not nomask:
3414 self._mask = self._mask.view(make_mask_descr(dtype), ndarray)
3415 # Try to reset the shape of the mask (if we don't have a void).
3416 # This raises a ValueError if the dtype change won't work.
3417 try:
3418 self._mask.shape = self.shape
3419 except (AttributeError, TypeError):
3420 pass
3422 @property
3423 def shape(self):
3424 return super(MaskedArray, self).shape
3426 @shape.setter
3427 def shape(self, shape):
3428 super(MaskedArray, type(self)).shape.__set__(self, shape)
3429 # Cannot use self._mask, since it may not (yet) exist when a
3430 # masked matrix sets the shape.
3431 if getmask(self) is not nomask:
3432 self._mask.shape = self.shape
3434 def __setmask__(self, mask, copy=False):
3435 """
3436 Set the mask.
3438 """
3439 idtype = self.dtype
3440 current_mask = self._mask
3441 if mask is masked:
3442 mask = True
3444 if current_mask is nomask:
3445 # Make sure the mask is set
3446 # Just don't do anything if there's nothing to do.
3447 if mask is nomask:
3448 return
3449 current_mask = self._mask = make_mask_none(self.shape, idtype)
3451 if idtype.names is None:
3452 # No named fields.
3453 # Hardmask: don't unmask the data
3454 if self._hardmask:
3455 current_mask |= mask
3456 # Softmask: set everything to False
3457 # If it's obviously a compatible scalar, use a quick update
3458 # method.
3459 elif isinstance(mask, (int, float, np.bool_, np.number)):
3460 current_mask[...] = mask
3461 # Otherwise fall back to the slower, general purpose way.
3462 else:
3463 current_mask.flat = mask
3464 else:
3465 # Named fields w/
3466 mdtype = current_mask.dtype
3467 mask = np.array(mask, copy=False)
3468 # Mask is a singleton
3469 if not mask.ndim:
3470 # It's a boolean : make a record
3471 if mask.dtype.kind == 'b':
3472 mask = np.array(tuple([mask.item()] * len(mdtype)),
3473 dtype=mdtype)
3474 # It's a record: make sure the dtype is correct
3475 else:
3476 mask = mask.astype(mdtype)
3477 # Mask is a sequence
3478 else:
3479 # Make sure the new mask is a ndarray with the proper dtype
3480 try:
3481 mask = np.array(mask, copy=copy, dtype=mdtype)
3482 # Or assume it's a sequence of bool/int
3483 except TypeError:
3484 mask = np.array([tuple([m] * len(mdtype)) for m in mask],
3485 dtype=mdtype)
3486 # Hardmask: don't unmask the data
3487 if self._hardmask:
3488 for n in idtype.names:
3489 current_mask[n] |= mask[n]
3490 # Softmask: set everything to False
3491 # If it's obviously a compatible scalar, use a quick update
3492 # method.
3493 elif isinstance(mask, (int, float, np.bool_, np.number)):
3494 current_mask[...] = mask
3495 # Otherwise fall back to the slower, general purpose way.
3496 else:
3497 current_mask.flat = mask
3498 # Reshape if needed
3499 if current_mask.shape:
3500 current_mask.shape = self.shape
3501 return
3503 _set_mask = __setmask__
3505 @property
3506 def mask(self):
3507 """ Current mask. """
3509 # We could try to force a reshape, but that wouldn't work in some
3510 # cases.
3511 # Return a view so that the dtype and shape cannot be changed in place
3512 # This still preserves nomask by identity
3513 return self._mask.view()
3515 @mask.setter
3516 def mask(self, value):
3517 self.__setmask__(value)
3519 @property
3520 def recordmask(self):
3521 """
3522 Get or set the mask of the array if it has no named fields. For
3523 structured arrays, returns a ndarray of booleans where entries are
3524 ``True`` if **all** the fields are masked, ``False`` otherwise:
3526 >>> x = np.ma.array([(1, 1), (2, 2), (3, 3), (4, 4), (5, 5)],
3527 ... mask=[(0, 0), (1, 0), (1, 1), (0, 1), (0, 0)],
3528 ... dtype=[('a', int), ('b', int)])
3529 >>> x.recordmask
3530 array([False, False, True, False, False])
3531 """
3533 _mask = self._mask.view(ndarray)
3534 if _mask.dtype.names is None:
3535 return _mask
3536 return np.all(flatten_structured_array(_mask), axis=-1)
3538 @recordmask.setter
3539 def recordmask(self, mask):
3540 raise NotImplementedError("Coming soon: setting the mask per records!")
3542 def harden_mask(self):
3543 """
3544 Force the mask to hard.
3546 Whether the mask of a masked array is hard or soft is determined by
3547 its `hardmask` property. `harden_mask` sets `hardmask` to True.
3549 See Also
3550 --------
3551 hardmask
3553 """
3554 self._hardmask = True
3555 return self
3557 def soften_mask(self):
3558 """
3559 Force the mask to soft.
3561 Whether the mask of a masked array is hard or soft is determined by
3562 its `hardmask` property. `soften_mask` sets `hardmask` to False.
3564 See Also
3565 --------
3566 hardmask
3568 """
3569 self._hardmask = False
3570 return self
3572 @property
3573 def hardmask(self):
3574 """ Hardness of the mask """
3575 return self._hardmask
3577 def unshare_mask(self):
3578 """
3579 Copy the mask and set the sharedmask flag to False.
3581 Whether the mask is shared between masked arrays can be seen from
3582 the `sharedmask` property. `unshare_mask` ensures the mask is not shared.
3583 A copy of the mask is only made if it was shared.
3585 See Also
3586 --------
3587 sharedmask
3589 """
3590 if self._sharedmask:
3591 self._mask = self._mask.copy()
3592 self._sharedmask = False
3593 return self
3595 @property
3596 def sharedmask(self):
3597 """ Share status of the mask (read-only). """
3598 return self._sharedmask
3600 def shrink_mask(self):
3601 """
3602 Reduce a mask to nomask when possible.
3604 Parameters
3605 ----------
3606 None
3608 Returns
3609 -------
3610 None
3612 Examples
3613 --------
3614 >>> x = np.ma.array([[1,2 ], [3, 4]], mask=[0]*4)
3615 >>> x.mask
3616 array([[False, False],
3617 [False, False]])
3618 >>> x.shrink_mask()
3619 masked_array(
3620 data=[[1, 2],
3621 [3, 4]],
3622 mask=False,
3623 fill_value=999999)
3624 >>> x.mask
3625 False
3627 """
3628 self._mask = _shrink_mask(self._mask)
3629 return self
3631 @property
3632 def baseclass(self):
3633 """ Class of the underlying data (read-only). """
3634 return self._baseclass
3636 def _get_data(self):
3637 """
3638 Returns the underlying data, as a view of the masked array.
3640 If the underlying data is a subclass of :class:`numpy.ndarray`, it is
3641 returned as such.
3643 >>> x = np.ma.array(np.matrix([[1, 2], [3, 4]]), mask=[[0, 1], [1, 0]])
3644 >>> x.data
3645 matrix([[1, 2],
3646 [3, 4]])
3648 The type of the data can be accessed through the :attr:`baseclass`
3649 attribute.
3650 """
3651 return ndarray.view(self, self._baseclass)
3653 _data = property(fget=_get_data)
3654 data = property(fget=_get_data)
3656 @property
3657 def flat(self):
3658 """ Return a flat iterator, or set a flattened version of self to value. """
3659 return MaskedIterator(self)
3661 @flat.setter
3662 def flat(self, value):
3663 y = self.ravel()
3664 y[:] = value
3666 @property
3667 def fill_value(self):
3668 """
3669 The filling value of the masked array is a scalar. When setting, None
3670 will set to a default based on the data type.
3672 Examples
3673 --------
3674 >>> for dt in [np.int32, np.int64, np.float64, np.complex128]:
3675 ... np.ma.array([0, 1], dtype=dt).get_fill_value()
3676 ...
3677 999999
3678 999999
3679 1e+20
3680 (1e+20+0j)
3682 >>> x = np.ma.array([0, 1.], fill_value=-np.inf)
3683 >>> x.fill_value
3684 -inf
3685 >>> x.fill_value = np.pi
3686 >>> x.fill_value
3687 3.1415926535897931 # may vary
3689 Reset to default:
3691 >>> x.fill_value = None
3692 >>> x.fill_value
3693 1e+20
3695 """
3696 if self._fill_value is None:
3697 self._fill_value = _check_fill_value(None, self.dtype)
3699 # Temporary workaround to account for the fact that str and bytes
3700 # scalars cannot be indexed with (), whereas all other numpy
3701 # scalars can. See issues #7259 and #7267.
3702 # The if-block can be removed after #7267 has been fixed.
3703 if isinstance(self._fill_value, ndarray):
3704 return self._fill_value[()]
3705 return self._fill_value
3707 @fill_value.setter
3708 def fill_value(self, value=None):
3709 target = _check_fill_value(value, self.dtype)
3710 if not target.ndim == 0:
3711 # 2019-11-12, 1.18.0
3712 warnings.warn(
3713 "Non-scalar arrays for the fill value are deprecated. Use "
3714 "arrays with scalar values instead. The filled function "
3715 "still supports any array as `fill_value`.",
3716 DeprecationWarning, stacklevel=2)
3718 _fill_value = self._fill_value
3719 if _fill_value is None:
3720 # Create the attribute if it was undefined
3721 self._fill_value = target
3722 else:
3723 # Don't overwrite the attribute, just fill it (for propagation)
3724 _fill_value[()] = target
3726 # kept for compatibility
3727 get_fill_value = fill_value.fget
3728 set_fill_value = fill_value.fset
3730 def filled(self, fill_value=None):
3731 """
3732 Return a copy of self, with masked values filled with a given value.
3733 **However**, if there are no masked values to fill, self will be
3734 returned instead as an ndarray.
3736 Parameters
3737 ----------
3738 fill_value : array_like, optional
3739 The value to use for invalid entries. Can be scalar or non-scalar.
3740 If non-scalar, the resulting ndarray must be broadcastable over
3741 input array. Default is None, in which case, the `fill_value`
3742 attribute of the array is used instead.
3744 Returns
3745 -------
3746 filled_array : ndarray
3747 A copy of ``self`` with invalid entries replaced by *fill_value*
3748 (be it the function argument or the attribute of ``self``), or
3749 ``self`` itself as an ndarray if there are no invalid entries to
3750 be replaced.
3752 Notes
3753 -----
3754 The result is **not** a MaskedArray!
3756 Examples
3757 --------
3758 >>> x = np.ma.array([1,2,3,4,5], mask=[0,0,1,0,1], fill_value=-999)
3759 >>> x.filled()
3760 array([ 1, 2, -999, 4, -999])
3761 >>> x.filled(fill_value=1000)
3762 array([ 1, 2, 1000, 4, 1000])
3763 >>> type(x.filled())
3764 <class 'numpy.ndarray'>
3766 Subclassing is preserved. This means that if, e.g., the data part of
3767 the masked array is a recarray, `filled` returns a recarray:
3769 >>> x = np.array([(-1, 2), (-3, 4)], dtype='i8,i8').view(np.recarray)
3770 >>> m = np.ma.array(x, mask=[(True, False), (False, True)])
3771 >>> m.filled()
3772 rec.array([(999999, 2), ( -3, 999999)],
3773 dtype=[('f0', '<i8'), ('f1', '<i8')])
3774 """
3775 m = self._mask
3776 if m is nomask:
3777 return self._data
3779 if fill_value is None:
3780 fill_value = self.fill_value
3781 else:
3782 fill_value = _check_fill_value(fill_value, self.dtype)
3784 if self is masked_singleton:
3785 return np.asanyarray(fill_value)
3787 if m.dtype.names is not None:
3788 result = self._data.copy('K')
3789 _recursive_filled(result, self._mask, fill_value)
3790 elif not m.any():
3791 return self._data
3792 else:
3793 result = self._data.copy('K')
3794 try:
3795 np.copyto(result, fill_value, where=m)
3796 except (TypeError, AttributeError):
3797 fill_value = narray(fill_value, dtype=object)
3798 d = result.astype(object)
3799 result = np.choose(m, (d, fill_value))
3800 except IndexError:
3801 # ok, if scalar
3802 if self._data.shape:
3803 raise
3804 elif m:
3805 result = np.array(fill_value, dtype=self.dtype)
3806 else:
3807 result = self._data
3808 return result
3810 def compressed(self):
3811 """
3812 Return all the non-masked data as a 1-D array.
3814 Returns
3815 -------
3816 data : ndarray
3817 A new `ndarray` holding the non-masked data is returned.
3819 Notes
3820 -----
3821 The result is **not** a MaskedArray!
3823 Examples
3824 --------
3825 >>> x = np.ma.array(np.arange(5), mask=[0]*2 + [1]*3)
3826 >>> x.compressed()
3827 array([0, 1])
3828 >>> type(x.compressed())
3829 <class 'numpy.ndarray'>
3831 """
3832 data = ndarray.ravel(self._data)
3833 if self._mask is not nomask:
3834 data = data.compress(np.logical_not(ndarray.ravel(self._mask)))
3835 return data
3837 def compress(self, condition, axis=None, out=None):
3838 """
3839 Return `a` where condition is ``True``.
3841 If condition is a `MaskedArray`, missing values are considered
3842 as ``False``.
3844 Parameters
3845 ----------
3846 condition : var
3847 Boolean 1-d array selecting which entries to return. If len(condition)
3848 is less than the size of a along the axis, then output is truncated
3849 to length of condition array.
3850 axis : {None, int}, optional
3851 Axis along which the operation must be performed.
3852 out : {None, ndarray}, optional
3853 Alternative output array in which to place the result. It must have
3854 the same shape as the expected output but the type will be cast if
3855 necessary.
3857 Returns
3858 -------
3859 result : MaskedArray
3860 A :class:`MaskedArray` object.
3862 Notes
3863 -----
3864 Please note the difference with :meth:`compressed` !
3865 The output of :meth:`compress` has a mask, the output of
3866 :meth:`compressed` does not.
3868 Examples
3869 --------
3870 >>> x = np.ma.array([[1,2,3],[4,5,6],[7,8,9]], mask=[0] + [1,0]*4)
3871 >>> x
3872 masked_array(
3873 data=[[1, --, 3],
3874 [--, 5, --],
3875 [7, --, 9]],
3876 mask=[[False, True, False],
3877 [ True, False, True],
3878 [False, True, False]],
3879 fill_value=999999)
3880 >>> x.compress([1, 0, 1])
3881 masked_array(data=[1, 3],
3882 mask=[False, False],
3883 fill_value=999999)
3885 >>> x.compress([1, 0, 1], axis=1)
3886 masked_array(
3887 data=[[1, 3],
3888 [--, --],
3889 [7, 9]],
3890 mask=[[False, False],
3891 [ True, True],
3892 [False, False]],
3893 fill_value=999999)
3895 """
3896 # Get the basic components
3897 (_data, _mask) = (self._data, self._mask)
3899 # Force the condition to a regular ndarray and forget the missing
3900 # values.
3901 condition = np.array(condition, copy=False, subok=False)
3903 _new = _data.compress(condition, axis=axis, out=out).view(type(self))
3904 _new._update_from(self)
3905 if _mask is not nomask:
3906 _new._mask = _mask.compress(condition, axis=axis)
3907 return _new
3909 def _insert_masked_print(self):
3910 """
3911 Replace masked values with masked_print_option, casting all innermost
3912 dtypes to object.
3913 """
3914 if masked_print_option.enabled():
3915 mask = self._mask
3916 if mask is nomask:
3917 res = self._data
3918 else:
3919 # convert to object array to make filled work
3920 data = self._data
3921 # For big arrays, to avoid a costly conversion to the
3922 # object dtype, extract the corners before the conversion.
3923 print_width = (self._print_width if self.ndim > 1
3924 else self._print_width_1d)
3925 for axis in range(self.ndim):
3926 if data.shape[axis] > print_width:
3927 ind = print_width // 2
3928 arr = np.split(data, (ind, -ind), axis=axis)
3929 data = np.concatenate((arr[0], arr[2]), axis=axis)
3930 arr = np.split(mask, (ind, -ind), axis=axis)
3931 mask = np.concatenate((arr[0], arr[2]), axis=axis)
3933 rdtype = _replace_dtype_fields(self.dtype, "O")
3934 res = data.astype(rdtype)
3935 _recursive_printoption(res, mask, masked_print_option)
3936 else:
3937 res = self.filled(self.fill_value)
3938 return res
3940 def __str__(self):
3941 return str(self._insert_masked_print())
3943 def __repr__(self):
3944 """
3945 Literal string representation.
3947 """
3948 if self._baseclass is np.ndarray:
3949 name = 'array'
3950 else:
3951 name = self._baseclass.__name__
3954 # 2016-11-19: Demoted to legacy format
3955 if np.get_printoptions()['legacy'] == '1.13':
3956 is_long = self.ndim > 1
3957 parameters = dict(
3958 name=name,
3959 nlen=" " * len(name),
3960 data=str(self),
3961 mask=str(self._mask),
3962 fill=str(self.fill_value),
3963 dtype=str(self.dtype)
3964 )
3965 is_structured = bool(self.dtype.names)
3966 key = '{}_{}'.format(
3967 'long' if is_long else 'short',
3968 'flx' if is_structured else 'std'
3969 )
3970 return _legacy_print_templates[key] % parameters
3972 prefix = f"masked_{name}("
3974 dtype_needed = (
3975 not np.core.arrayprint.dtype_is_implied(self.dtype) or
3976 np.all(self.mask) or
3977 self.size == 0
3978 )
3980 # determine which keyword args need to be shown
3981 keys = ['data', 'mask', 'fill_value']
3982 if dtype_needed:
3983 keys.append('dtype')
3985 # array has only one row (non-column)
3986 is_one_row = builtins.all(dim == 1 for dim in self.shape[:-1])
3988 # choose what to indent each keyword with
3989 min_indent = 2
3990 if is_one_row:
3991 # first key on the same line as the type, remaining keys
3992 # aligned by equals
3993 indents = {}
3994 indents[keys[0]] = prefix
3995 for k in keys[1:]:
3996 n = builtins.max(min_indent, len(prefix + keys[0]) - len(k))
3997 indents[k] = ' ' * n
3998 prefix = '' # absorbed into the first indent
3999 else:
4000 # each key on its own line, indented by two spaces
4001 indents = {k: ' ' * min_indent for k in keys}
4002 prefix = prefix + '\n' # first key on the next line
4004 # format the field values
4005 reprs = {}
4006 reprs['data'] = np.array2string(
4007 self._insert_masked_print(),
4008 separator=", ",
4009 prefix=indents['data'] + 'data=',
4010 suffix=',')
4011 reprs['mask'] = np.array2string(
4012 self._mask,
4013 separator=", ",
4014 prefix=indents['mask'] + 'mask=',
4015 suffix=',')
4016 reprs['fill_value'] = repr(self.fill_value)
4017 if dtype_needed:
4018 reprs['dtype'] = np.core.arrayprint.dtype_short_repr(self.dtype)
4020 # join keys with values and indentations
4021 result = ',\n'.join(
4022 '{}{}={}'.format(indents[k], k, reprs[k])
4023 for k in keys
4024 )
4025 return prefix + result + ')'
4027 def _delegate_binop(self, other):
4028 # This emulates the logic in
4029 # private/binop_override.h:forward_binop_should_defer
4030 if isinstance(other, type(self)):
4031 return False
4032 array_ufunc = getattr(other, "__array_ufunc__", False)
4033 if array_ufunc is False:
4034 other_priority = getattr(other, "__array_priority__", -1000000)
4035 return self.__array_priority__ < other_priority
4036 else:
4037 # If array_ufunc is not None, it will be called inside the ufunc;
4038 # None explicitly tells us to not call the ufunc, i.e., defer.
4039 return array_ufunc is None
4041 def _comparison(self, other, compare):
4042 """Compare self with other using operator.eq or operator.ne.
4044 When either of the elements is masked, the result is masked as well,
4045 but the underlying boolean data are still set, with self and other
4046 considered equal if both are masked, and unequal otherwise.
4048 For structured arrays, all fields are combined, with masked values
4049 ignored. The result is masked if all fields were masked, with self
4050 and other considered equal only if both were fully masked.
4051 """
4052 omask = getmask(other)
4053 smask = self.mask
4054 mask = mask_or(smask, omask, copy=True)
4056 odata = getdata(other)
4057 if mask.dtype.names is not None:
4058 # For possibly masked structured arrays we need to be careful,
4059 # since the standard structured array comparison will use all
4060 # fields, masked or not. To avoid masked fields influencing the
4061 # outcome, we set all masked fields in self to other, so they'll
4062 # count as equal. To prepare, we ensure we have the right shape.
4063 broadcast_shape = np.broadcast(self, odata).shape
4064 sbroadcast = np.broadcast_to(self, broadcast_shape, subok=True)
4065 sbroadcast._mask = mask
4066 sdata = sbroadcast.filled(odata)
4067 # Now take care of the mask; the merged mask should have an item
4068 # masked if all fields were masked (in one and/or other).
4069 mask = (mask == np.ones((), mask.dtype))
4071 else:
4072 # For regular arrays, just use the data as they come.
4073 sdata = self.data
4075 check = compare(sdata, odata)
4077 if isinstance(check, (np.bool_, bool)):
4078 return masked if mask else check
4080 if mask is not nomask:
4081 # Adjust elements that were masked, which should be treated
4082 # as equal if masked in both, unequal if masked in one.
4083 # Note that this works automatically for structured arrays too.
4084 check = np.where(mask, compare(smask, omask), check)
4085 if mask.shape != check.shape:
4086 # Guarantee consistency of the shape, making a copy since the
4087 # the mask may need to get written to later.
4088 mask = np.broadcast_to(mask, check.shape).copy()
4090 check = check.view(type(self))
4091 check._update_from(self)
4092 check._mask = mask
4094 # Cast fill value to bool_ if needed. If it cannot be cast, the
4095 # default boolean fill value is used.
4096 if check._fill_value is not None:
4097 try:
4098 fill = _check_fill_value(check._fill_value, np.bool_)
4099 except (TypeError, ValueError):
4100 fill = _check_fill_value(None, np.bool_)
4101 check._fill_value = fill
4103 return check
4105 def __eq__(self, other):
4106 """Check whether other equals self elementwise.
4108 When either of the elements is masked, the result is masked as well,
4109 but the underlying boolean data are still set, with self and other
4110 considered equal if both are masked, and unequal otherwise.
4112 For structured arrays, all fields are combined, with masked values
4113 ignored. The result is masked if all fields were masked, with self
4114 and other considered equal only if both were fully masked.
4115 """
4116 return self._comparison(other, operator.eq)
4118 def __ne__(self, other):
4119 """Check whether other does not equal self elementwise.
4121 When either of the elements is masked, the result is masked as well,
4122 but the underlying boolean data are still set, with self and other
4123 considered equal if both are masked, and unequal otherwise.
4125 For structured arrays, all fields are combined, with masked values
4126 ignored. The result is masked if all fields were masked, with self
4127 and other considered equal only if both were fully masked.
4128 """
4129 return self._comparison(other, operator.ne)
4131 def __add__(self, other):
4132 """
4133 Add self to other, and return a new masked array.
4135 """
4136 if self._delegate_binop(other):
4137 return NotImplemented
4138 return add(self, other)
4140 def __radd__(self, other):
4141 """
4142 Add other to self, and return a new masked array.
4144 """
4145 # In analogy with __rsub__ and __rdiv__, use original order:
4146 # we get here from `other + self`.
4147 return add(other, self)
4149 def __sub__(self, other):
4150 """
4151 Subtract other from self, and return a new masked array.
4153 """
4154 if self._delegate_binop(other):
4155 return NotImplemented
4156 return subtract(self, other)
4158 def __rsub__(self, other):
4159 """
4160 Subtract self from other, and return a new masked array.
4162 """
4163 return subtract(other, self)
4165 def __mul__(self, other):
4166 "Multiply self by other, and return a new masked array."
4167 if self._delegate_binop(other):
4168 return NotImplemented
4169 return multiply(self, other)
4171 def __rmul__(self, other):
4172 """
4173 Multiply other by self, and return a new masked array.
4175 """
4176 # In analogy with __rsub__ and __rdiv__, use original order:
4177 # we get here from `other * self`.
4178 return multiply(other, self)
4180 def __div__(self, other):
4181 """
4182 Divide other into self, and return a new masked array.
4184 """
4185 if self._delegate_binop(other):
4186 return NotImplemented
4187 return divide(self, other)
4189 def __truediv__(self, other):
4190 """
4191 Divide other into self, and return a new masked array.
4193 """
4194 if self._delegate_binop(other):
4195 return NotImplemented
4196 return true_divide(self, other)
4198 def __rtruediv__(self, other):
4199 """
4200 Divide self into other, and return a new masked array.
4202 """
4203 return true_divide(other, self)
4205 def __floordiv__(self, other):
4206 """
4207 Divide other into self, and return a new masked array.
4209 """
4210 if self._delegate_binop(other):
4211 return NotImplemented
4212 return floor_divide(self, other)
4214 def __rfloordiv__(self, other):
4215 """
4216 Divide self into other, and return a new masked array.
4218 """
4219 return floor_divide(other, self)
4221 def __pow__(self, other):
4222 """
4223 Raise self to the power other, masking the potential NaNs/Infs
4225 """
4226 if self._delegate_binop(other):
4227 return NotImplemented
4228 return power(self, other)
4230 def __rpow__(self, other):
4231 """
4232 Raise other to the power self, masking the potential NaNs/Infs
4234 """
4235 return power(other, self)
4237 def __iadd__(self, other):
4238 """
4239 Add other to self in-place.
4241 """
4242 m = getmask(other)
4243 if self._mask is nomask:
4244 if m is not nomask and m.any():
4245 self._mask = make_mask_none(self.shape, self.dtype)
4246 self._mask += m
4247 else:
4248 if m is not nomask:
4249 self._mask += m
4250 self._data.__iadd__(np.where(self._mask, self.dtype.type(0),
4251 getdata(other)))
4252 return self
4254 def __isub__(self, other):
4255 """
4256 Subtract other from self in-place.
4258 """
4259 m = getmask(other)
4260 if self._mask is nomask:
4261 if m is not nomask and m.any():
4262 self._mask = make_mask_none(self.shape, self.dtype)
4263 self._mask += m
4264 elif m is not nomask:
4265 self._mask += m
4266 self._data.__isub__(np.where(self._mask, self.dtype.type(0),
4267 getdata(other)))
4268 return self
4270 def __imul__(self, other):
4271 """
4272 Multiply self by other in-place.
4274 """
4275 m = getmask(other)
4276 if self._mask is nomask:
4277 if m is not nomask and m.any():
4278 self._mask = make_mask_none(self.shape, self.dtype)
4279 self._mask += m
4280 elif m is not nomask:
4281 self._mask += m
4282 self._data.__imul__(np.where(self._mask, self.dtype.type(1),
4283 getdata(other)))
4284 return self
4286 def __idiv__(self, other):
4287 """
4288 Divide self by other in-place.
4290 """
4291 other_data = getdata(other)
4292 dom_mask = _DomainSafeDivide().__call__(self._data, other_data)
4293 other_mask = getmask(other)
4294 new_mask = mask_or(other_mask, dom_mask)
4295 # The following 3 lines control the domain filling
4296 if dom_mask.any():
4297 (_, fval) = ufunc_fills[np.divide]
4298 other_data = np.where(dom_mask, fval, other_data)
4299 self._mask |= new_mask
4300 self._data.__idiv__(np.where(self._mask, self.dtype.type(1),
4301 other_data))
4302 return self
4304 def __ifloordiv__(self, other):
4305 """
4306 Floor divide self by other in-place.
4308 """
4309 other_data = getdata(other)
4310 dom_mask = _DomainSafeDivide().__call__(self._data, other_data)
4311 other_mask = getmask(other)
4312 new_mask = mask_or(other_mask, dom_mask)
4313 # The following 3 lines control the domain filling
4314 if dom_mask.any():
4315 (_, fval) = ufunc_fills[np.floor_divide]
4316 other_data = np.where(dom_mask, fval, other_data)
4317 self._mask |= new_mask
4318 self._data.__ifloordiv__(np.where(self._mask, self.dtype.type(1),
4319 other_data))
4320 return self
4322 def __itruediv__(self, other):
4323 """
4324 True divide self by other in-place.
4326 """
4327 other_data = getdata(other)
4328 dom_mask = _DomainSafeDivide().__call__(self._data, other_data)
4329 other_mask = getmask(other)
4330 new_mask = mask_or(other_mask, dom_mask)
4331 # The following 3 lines control the domain filling
4332 if dom_mask.any():
4333 (_, fval) = ufunc_fills[np.true_divide]
4334 other_data = np.where(dom_mask, fval, other_data)
4335 self._mask |= new_mask
4336 self._data.__itruediv__(np.where(self._mask, self.dtype.type(1),
4337 other_data))
4338 return self
4340 def __ipow__(self, other):
4341 """
4342 Raise self to the power other, in place.
4344 """
4345 other_data = getdata(other)
4346 other_mask = getmask(other)
4347 with np.errstate(divide='ignore', invalid='ignore'):
4348 self._data.__ipow__(np.where(self._mask, self.dtype.type(1),
4349 other_data))
4350 invalid = np.logical_not(np.isfinite(self._data))
4351 if invalid.any():
4352 if self._mask is not nomask:
4353 self._mask |= invalid
4354 else:
4355 self._mask = invalid
4356 np.copyto(self._data, self.fill_value, where=invalid)
4357 new_mask = mask_or(other_mask, invalid)
4358 self._mask = mask_or(self._mask, new_mask)
4359 return self
4361 def __float__(self):
4362 """
4363 Convert to float.
4365 """
4366 if self.size > 1:
4367 raise TypeError("Only length-1 arrays can be converted "
4368 "to Python scalars")
4369 elif self._mask:
4370 warnings.warn("Warning: converting a masked element to nan.", stacklevel=2)
4371 return np.nan
4372 return float(self.item())
4374 def __int__(self):
4375 """
4376 Convert to int.
4378 """
4379 if self.size > 1:
4380 raise TypeError("Only length-1 arrays can be converted "
4381 "to Python scalars")
4382 elif self._mask:
4383 raise MaskError('Cannot convert masked element to a Python int.')
4384 return int(self.item())
4386 @property
4387 def imag(self):
4388 """
4389 The imaginary part of the masked array.
4391 This property is a view on the imaginary part of this `MaskedArray`.
4393 See Also
4394 --------
4395 real
4397 Examples
4398 --------
4399 >>> x = np.ma.array([1+1.j, -2j, 3.45+1.6j], mask=[False, True, False])
4400 >>> x.imag
4401 masked_array(data=[1.0, --, 1.6],
4402 mask=[False, True, False],
4403 fill_value=1e+20)
4405 """
4406 result = self._data.imag.view(type(self))
4407 result.__setmask__(self._mask)
4408 return result
4410 # kept for compatibility
4411 get_imag = imag.fget
4413 @property
4414 def real(self):
4415 """
4416 The real part of the masked array.
4418 This property is a view on the real part of this `MaskedArray`.
4420 See Also
4421 --------
4422 imag
4424 Examples
4425 --------
4426 >>> x = np.ma.array([1+1.j, -2j, 3.45+1.6j], mask=[False, True, False])
4427 >>> x.real
4428 masked_array(data=[1.0, --, 3.45],
4429 mask=[False, True, False],
4430 fill_value=1e+20)
4432 """
4433 result = self._data.real.view(type(self))
4434 result.__setmask__(self._mask)
4435 return result
4437 # kept for compatibility
4438 get_real = real.fget
4440 def count(self, axis=None, keepdims=np._NoValue):
4441 """
4442 Count the non-masked elements of the array along the given axis.
4444 Parameters
4445 ----------
4446 axis : None or int or tuple of ints, optional
4447 Axis or axes along which the count is performed.
4448 The default, None, performs the count over all
4449 the dimensions of the input array. `axis` may be negative, in
4450 which case it counts from the last to the first axis.
4452 .. versionadded:: 1.10.0
4454 If this is a tuple of ints, the count is performed on multiple
4455 axes, instead of a single axis or all the axes as before.
4456 keepdims : bool, optional
4457 If this is set to True, the axes which are reduced are left
4458 in the result as dimensions with size one. With this option,
4459 the result will broadcast correctly against the array.
4461 Returns
4462 -------
4463 result : ndarray or scalar
4464 An array with the same shape as the input array, with the specified
4465 axis removed. If the array is a 0-d array, or if `axis` is None, a
4466 scalar is returned.
4468 See Also
4469 --------
4470 count_masked : Count masked elements in array or along a given axis.
4472 Examples
4473 --------
4474 >>> import numpy.ma as ma
4475 >>> a = ma.arange(6).reshape((2, 3))
4476 >>> a[1, :] = ma.masked
4477 >>> a
4478 masked_array(
4479 data=[[0, 1, 2],
4480 [--, --, --]],
4481 mask=[[False, False, False],
4482 [ True, True, True]],
4483 fill_value=999999)
4484 >>> a.count()
4485 3
4487 When the `axis` keyword is specified an array of appropriate size is
4488 returned.
4490 >>> a.count(axis=0)
4491 array([1, 1, 1])
4492 >>> a.count(axis=1)
4493 array([3, 0])
4495 """
4496 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims}
4498 m = self._mask
4499 # special case for matrices (we assume no other subclasses modify
4500 # their dimensions)
4501 if isinstance(self.data, np.matrix):
4502 if m is nomask:
4503 m = np.zeros(self.shape, dtype=np.bool_)
4504 m = m.view(type(self.data))
4506 if m is nomask:
4507 # compare to _count_reduce_items in _methods.py
4509 if self.shape == ():
4510 if axis not in (None, 0):
4511 raise np.AxisError(axis=axis, ndim=self.ndim)
4512 return 1
4513 elif axis is None:
4514 if kwargs.get('keepdims', False):
4515 return np.array(self.size, dtype=np.intp, ndmin=self.ndim)
4516 return self.size
4518 axes = normalize_axis_tuple(axis, self.ndim)
4519 items = 1
4520 for ax in axes:
4521 items *= self.shape[ax]
4523 if kwargs.get('keepdims', False):
4524 out_dims = list(self.shape)
4525 for a in axes:
4526 out_dims[a] = 1
4527 else:
4528 out_dims = [d for n, d in enumerate(self.shape)
4529 if n not in axes]
4530 # make sure to return a 0-d array if axis is supplied
4531 return np.full(out_dims, items, dtype=np.intp)
4533 # take care of the masked singleton
4534 if self is masked:
4535 return 0
4537 return (~m).sum(axis=axis, dtype=np.intp, **kwargs)
4539 def ravel(self, order='C'):
4540 """
4541 Returns a 1D version of self, as a view.
4543 Parameters
4544 ----------
4545 order : {'C', 'F', 'A', 'K'}, optional
4546 The elements of `a` are read using this index order. 'C' means to
4547 index the elements in C-like order, with the last axis index
4548 changing fastest, back to the first axis index changing slowest.
4549 'F' means to index the elements in Fortran-like index order, with
4550 the first index changing fastest, and the last index changing
4551 slowest. Note that the 'C' and 'F' options take no account of the
4552 memory layout of the underlying array, and only refer to the order
4553 of axis indexing. 'A' means to read the elements in Fortran-like
4554 index order if `m` is Fortran *contiguous* in memory, C-like order
4555 otherwise. 'K' means to read the elements in the order they occur
4556 in memory, except for reversing the data when strides are negative.
4557 By default, 'C' index order is used.
4559 Returns
4560 -------
4561 MaskedArray
4562 Output view is of shape ``(self.size,)`` (or
4563 ``(np.ma.product(self.shape),)``).
4565 Examples
4566 --------
4567 >>> x = np.ma.array([[1,2,3],[4,5,6],[7,8,9]], mask=[0] + [1,0]*4)
4568 >>> x
4569 masked_array(
4570 data=[[1, --, 3],
4571 [--, 5, --],
4572 [7, --, 9]],
4573 mask=[[False, True, False],
4574 [ True, False, True],
4575 [False, True, False]],
4576 fill_value=999999)
4577 >>> x.ravel()
4578 masked_array(data=[1, --, 3, --, 5, --, 7, --, 9],
4579 mask=[False, True, False, True, False, True, False, True,
4580 False],
4581 fill_value=999999)
4583 """
4584 r = ndarray.ravel(self._data, order=order).view(type(self))
4585 r._update_from(self)
4586 if self._mask is not nomask:
4587 r._mask = ndarray.ravel(self._mask, order=order).reshape(r.shape)
4588 else:
4589 r._mask = nomask
4590 return r
4593 def reshape(self, *s, **kwargs):
4594 """
4595 Give a new shape to the array without changing its data.
4597 Returns a masked array containing the same data, but with a new shape.
4598 The result is a view on the original array; if this is not possible, a
4599 ValueError is raised.
4601 Parameters
4602 ----------
4603 shape : int or tuple of ints
4604 The new shape should be compatible with the original shape. If an
4605 integer is supplied, then the result will be a 1-D array of that
4606 length.
4607 order : {'C', 'F'}, optional
4608 Determines whether the array data should be viewed as in C
4609 (row-major) or FORTRAN (column-major) order.
4611 Returns
4612 -------
4613 reshaped_array : array
4614 A new view on the array.
4616 See Also
4617 --------
4618 reshape : Equivalent function in the masked array module.
4619 numpy.ndarray.reshape : Equivalent method on ndarray object.
4620 numpy.reshape : Equivalent function in the NumPy module.
4622 Notes
4623 -----
4624 The reshaping operation cannot guarantee that a copy will not be made,
4625 to modify the shape in place, use ``a.shape = s``
4627 Examples
4628 --------
4629 >>> x = np.ma.array([[1,2],[3,4]], mask=[1,0,0,1])
4630 >>> x
4631 masked_array(
4632 data=[[--, 2],
4633 [3, --]],
4634 mask=[[ True, False],
4635 [False, True]],
4636 fill_value=999999)
4637 >>> x = x.reshape((4,1))
4638 >>> x
4639 masked_array(
4640 data=[[--],
4641 [2],
4642 [3],
4643 [--]],
4644 mask=[[ True],
4645 [False],
4646 [False],
4647 [ True]],
4648 fill_value=999999)
4650 """
4651 kwargs.update(order=kwargs.get('order', 'C'))
4652 result = self._data.reshape(*s, **kwargs).view(type(self))
4653 result._update_from(self)
4654 mask = self._mask
4655 if mask is not nomask:
4656 result._mask = mask.reshape(*s, **kwargs)
4657 return result
4659 def resize(self, newshape, refcheck=True, order=False):
4660 """
4661 .. warning::
4663 This method does nothing, except raise a ValueError exception. A
4664 masked array does not own its data and therefore cannot safely be
4665 resized in place. Use the `numpy.ma.resize` function instead.
4667 This method is difficult to implement safely and may be deprecated in
4668 future releases of NumPy.
4670 """
4671 # Note : the 'order' keyword looks broken, let's just drop it
4672 errmsg = "A masked array does not own its data "\
4673 "and therefore cannot be resized.\n" \
4674 "Use the numpy.ma.resize function instead."
4675 raise ValueError(errmsg)
4677 def put(self, indices, values, mode='raise'):
4678 """
4679 Set storage-indexed locations to corresponding values.
4681 Sets self._data.flat[n] = values[n] for each n in indices.
4682 If `values` is shorter than `indices` then it will repeat.
4683 If `values` has some masked values, the initial mask is updated
4684 in consequence, else the corresponding values are unmasked.
4686 Parameters
4687 ----------
4688 indices : 1-D array_like
4689 Target indices, interpreted as integers.
4690 values : array_like
4691 Values to place in self._data copy at target indices.
4692 mode : {'raise', 'wrap', 'clip'}, optional
4693 Specifies how out-of-bounds indices will behave.
4694 'raise' : raise an error.
4695 'wrap' : wrap around.
4696 'clip' : clip to the range.
4698 Notes
4699 -----
4700 `values` can be a scalar or length 1 array.
4702 Examples
4703 --------
4704 >>> x = np.ma.array([[1,2,3],[4,5,6],[7,8,9]], mask=[0] + [1,0]*4)
4705 >>> x
4706 masked_array(
4707 data=[[1, --, 3],
4708 [--, 5, --],
4709 [7, --, 9]],
4710 mask=[[False, True, False],
4711 [ True, False, True],
4712 [False, True, False]],
4713 fill_value=999999)
4714 >>> x.put([0,4,8],[10,20,30])
4715 >>> x
4716 masked_array(
4717 data=[[10, --, 3],
4718 [--, 20, --],
4719 [7, --, 30]],
4720 mask=[[False, True, False],
4721 [ True, False, True],
4722 [False, True, False]],
4723 fill_value=999999)
4725 >>> x.put(4,999)
4726 >>> x
4727 masked_array(
4728 data=[[10, --, 3],
4729 [--, 999, --],
4730 [7, --, 30]],
4731 mask=[[False, True, False],
4732 [ True, False, True],
4733 [False, True, False]],
4734 fill_value=999999)
4736 """
4737 # Hard mask: Get rid of the values/indices that fall on masked data
4738 if self._hardmask and self._mask is not nomask:
4739 mask = self._mask[indices]
4740 indices = narray(indices, copy=False)
4741 values = narray(values, copy=False, subok=True)
4742 values.resize(indices.shape)
4743 indices = indices[~mask]
4744 values = values[~mask]
4746 self._data.put(indices, values, mode=mode)
4748 # short circuit if neither self nor values are masked
4749 if self._mask is nomask and getmask(values) is nomask:
4750 return
4752 m = getmaskarray(self)
4754 if getmask(values) is nomask:
4755 m.put(indices, False, mode=mode)
4756 else:
4757 m.put(indices, values._mask, mode=mode)
4758 m = make_mask(m, copy=False, shrink=True)
4759 self._mask = m
4760 return
4762 def ids(self):
4763 """
4764 Return the addresses of the data and mask areas.
4766 Parameters
4767 ----------
4768 None
4770 Examples
4771 --------
4772 >>> x = np.ma.array([1, 2, 3], mask=[0, 1, 1])
4773 >>> x.ids()
4774 (166670640, 166659832) # may vary
4776 If the array has no mask, the address of `nomask` is returned. This address
4777 is typically not close to the data in memory:
4779 >>> x = np.ma.array([1, 2, 3])
4780 >>> x.ids()
4781 (166691080, 3083169284) # may vary
4783 """
4784 if self._mask is nomask:
4785 return (self.ctypes.data, id(nomask))
4786 return (self.ctypes.data, self._mask.ctypes.data)
4788 def iscontiguous(self):
4789 """
4790 Return a boolean indicating whether the data is contiguous.
4792 Parameters
4793 ----------
4794 None
4796 Examples
4797 --------
4798 >>> x = np.ma.array([1, 2, 3])
4799 >>> x.iscontiguous()
4800 True
4802 `iscontiguous` returns one of the flags of the masked array:
4804 >>> x.flags
4805 C_CONTIGUOUS : True
4806 F_CONTIGUOUS : True
4807 OWNDATA : False
4808 WRITEABLE : True
4809 ALIGNED : True
4810 WRITEBACKIFCOPY : False
4811 UPDATEIFCOPY : False
4813 """
4814 return self.flags['CONTIGUOUS']
4816 def all(self, axis=None, out=None, keepdims=np._NoValue):
4817 """
4818 Returns True if all elements evaluate to True.
4820 The output array is masked where all the values along the given axis
4821 are masked: if the output would have been a scalar and that all the
4822 values are masked, then the output is `masked`.
4824 Refer to `numpy.all` for full documentation.
4826 See Also
4827 --------
4828 numpy.ndarray.all : corresponding function for ndarrays
4829 numpy.all : equivalent function
4831 Examples
4832 --------
4833 >>> np.ma.array([1,2,3]).all()
4834 True
4835 >>> a = np.ma.array([1,2,3], mask=True)
4836 >>> (a.all() is np.ma.masked)
4837 True
4839 """
4840 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims}
4842 mask = _check_mask_axis(self._mask, axis, **kwargs)
4843 if out is None:
4844 d = self.filled(True).all(axis=axis, **kwargs).view(type(self))
4845 if d.ndim:
4846 d.__setmask__(mask)
4847 elif mask:
4848 return masked
4849 return d
4850 self.filled(True).all(axis=axis, out=out, **kwargs)
4851 if isinstance(out, MaskedArray):
4852 if out.ndim or mask:
4853 out.__setmask__(mask)
4854 return out
4856 def any(self, axis=None, out=None, keepdims=np._NoValue):
4857 """
4858 Returns True if any of the elements of `a` evaluate to True.
4860 Masked values are considered as False during computation.
4862 Refer to `numpy.any` for full documentation.
4864 See Also
4865 --------
4866 numpy.ndarray.any : corresponding function for ndarrays
4867 numpy.any : equivalent function
4869 """
4870 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims}
4872 mask = _check_mask_axis(self._mask, axis, **kwargs)
4873 if out is None:
4874 d = self.filled(False).any(axis=axis, **kwargs).view(type(self))
4875 if d.ndim:
4876 d.__setmask__(mask)
4877 elif mask:
4878 d = masked
4879 return d
4880 self.filled(False).any(axis=axis, out=out, **kwargs)
4881 if isinstance(out, MaskedArray):
4882 if out.ndim or mask:
4883 out.__setmask__(mask)
4884 return out
4886 def nonzero(self):
4887 """
4888 Return the indices of unmasked elements that are not zero.
4890 Returns a tuple of arrays, one for each dimension, containing the
4891 indices of the non-zero elements in that dimension. The corresponding
4892 non-zero values can be obtained with::
4894 a[a.nonzero()]
4896 To group the indices by element, rather than dimension, use
4897 instead::
4899 np.transpose(a.nonzero())
4901 The result of this is always a 2d array, with a row for each non-zero
4902 element.
4904 Parameters
4905 ----------
4906 None
4908 Returns
4909 -------
4910 tuple_of_arrays : tuple
4911 Indices of elements that are non-zero.
4913 See Also
4914 --------
4915 numpy.nonzero :
4916 Function operating on ndarrays.
4917 flatnonzero :
4918 Return indices that are non-zero in the flattened version of the input
4919 array.
4920 numpy.ndarray.nonzero :
4921 Equivalent ndarray method.
4922 count_nonzero :
4923 Counts the number of non-zero elements in the input array.
4925 Examples
4926 --------
4927 >>> import numpy.ma as ma
4928 >>> x = ma.array(np.eye(3))
4929 >>> x
4930 masked_array(
4931 data=[[1., 0., 0.],
4932 [0., 1., 0.],
4933 [0., 0., 1.]],
4934 mask=False,
4935 fill_value=1e+20)
4936 >>> x.nonzero()
4937 (array([0, 1, 2]), array([0, 1, 2]))
4939 Masked elements are ignored.
4941 >>> x[1, 1] = ma.masked
4942 >>> x
4943 masked_array(
4944 data=[[1.0, 0.0, 0.0],
4945 [0.0, --, 0.0],
4946 [0.0, 0.0, 1.0]],
4947 mask=[[False, False, False],
4948 [False, True, False],
4949 [False, False, False]],
4950 fill_value=1e+20)
4951 >>> x.nonzero()
4952 (array([0, 2]), array([0, 2]))
4954 Indices can also be grouped by element.
4956 >>> np.transpose(x.nonzero())
4957 array([[0, 0],
4958 [2, 2]])
4960 A common use for ``nonzero`` is to find the indices of an array, where
4961 a condition is True. Given an array `a`, the condition `a` > 3 is a
4962 boolean array and since False is interpreted as 0, ma.nonzero(a > 3)
4963 yields the indices of the `a` where the condition is true.
4965 >>> a = ma.array([[1,2,3],[4,5,6],[7,8,9]])
4966 >>> a > 3
4967 masked_array(
4968 data=[[False, False, False],
4969 [ True, True, True],
4970 [ True, True, True]],
4971 mask=False,
4972 fill_value=True)
4973 >>> ma.nonzero(a > 3)
4974 (array([1, 1, 1, 2, 2, 2]), array([0, 1, 2, 0, 1, 2]))
4976 The ``nonzero`` method of the condition array can also be called.
4978 >>> (a > 3).nonzero()
4979 (array([1, 1, 1, 2, 2, 2]), array([0, 1, 2, 0, 1, 2]))
4981 """
4982 return narray(self.filled(0), copy=False).nonzero()
4984 def trace(self, offset=0, axis1=0, axis2=1, dtype=None, out=None):
4985 """
4986 (this docstring should be overwritten)
4987 """
4988 #!!!: implement out + test!
4989 m = self._mask
4990 if m is nomask:
4991 result = super(MaskedArray, self).trace(offset=offset, axis1=axis1,
4992 axis2=axis2, out=out)
4993 return result.astype(dtype)
4994 else:
4995 D = self.diagonal(offset=offset, axis1=axis1, axis2=axis2)
4996 return D.astype(dtype).filled(0).sum(axis=-1, out=out)
4997 trace.__doc__ = ndarray.trace.__doc__
4999 def dot(self, b, out=None, strict=False):
5000 """
5001 a.dot(b, out=None)
5003 Masked dot product of two arrays. Note that `out` and `strict` are
5004 located in different positions than in `ma.dot`. In order to
5005 maintain compatibility with the functional version, it is
5006 recommended that the optional arguments be treated as keyword only.
5007 At some point that may be mandatory.
5009 .. versionadded:: 1.10.0
5011 Parameters
5012 ----------
5013 b : masked_array_like
5014 Inputs array.
5015 out : masked_array, optional
5016 Output argument. This must have the exact kind that would be
5017 returned if it was not used. In particular, it must have the
5018 right type, must be C-contiguous, and its dtype must be the
5019 dtype that would be returned for `ma.dot(a,b)`. This is a
5020 performance feature. Therefore, if these conditions are not
5021 met, an exception is raised, instead of attempting to be
5022 flexible.
5023 strict : bool, optional
5024 Whether masked data are propagated (True) or set to 0 (False)
5025 for the computation. Default is False. Propagating the mask
5026 means that if a masked value appears in a row or column, the
5027 whole row or column is considered masked.
5029 .. versionadded:: 1.10.2
5031 See Also
5032 --------
5033 numpy.ma.dot : equivalent function
5035 """
5036 return dot(self, b, out=out, strict=strict)
5038 def sum(self, axis=None, dtype=None, out=None, keepdims=np._NoValue):
5039 """
5040 Return the sum of the array elements over the given axis.
5042 Masked elements are set to 0 internally.
5044 Refer to `numpy.sum` for full documentation.
5046 See Also
5047 --------
5048 numpy.ndarray.sum : corresponding function for ndarrays
5049 numpy.sum : equivalent function
5051 Examples
5052 --------
5053 >>> x = np.ma.array([[1,2,3],[4,5,6],[7,8,9]], mask=[0] + [1,0]*4)
5054 >>> x
5055 masked_array(
5056 data=[[1, --, 3],
5057 [--, 5, --],
5058 [7, --, 9]],
5059 mask=[[False, True, False],
5060 [ True, False, True],
5061 [False, True, False]],
5062 fill_value=999999)
5063 >>> x.sum()
5064 25
5065 >>> x.sum(axis=1)
5066 masked_array(data=[4, 5, 16],
5067 mask=[False, False, False],
5068 fill_value=999999)
5069 >>> x.sum(axis=0)
5070 masked_array(data=[8, 5, 12],
5071 mask=[False, False, False],
5072 fill_value=999999)
5073 >>> print(type(x.sum(axis=0, dtype=np.int64)[0]))
5074 <class 'numpy.int64'>
5076 """
5077 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims}
5079 _mask = self._mask
5080 newmask = _check_mask_axis(_mask, axis, **kwargs)
5081 # No explicit output
5082 if out is None:
5083 result = self.filled(0).sum(axis, dtype=dtype, **kwargs)
5084 rndim = getattr(result, 'ndim', 0)
5085 if rndim:
5086 result = result.view(type(self))
5087 result.__setmask__(newmask)
5088 elif newmask:
5089 result = masked
5090 return result
5091 # Explicit output
5092 result = self.filled(0).sum(axis, dtype=dtype, out=out, **kwargs)
5093 if isinstance(out, MaskedArray):
5094 outmask = getmask(out)
5095 if outmask is nomask:
5096 outmask = out._mask = make_mask_none(out.shape)
5097 outmask.flat = newmask
5098 return out
5100 def cumsum(self, axis=None, dtype=None, out=None):
5101 """
5102 Return the cumulative sum of the array elements over the given axis.
5104 Masked values are set to 0 internally during the computation.
5105 However, their position is saved, and the result will be masked at
5106 the same locations.
5108 Refer to `numpy.cumsum` for full documentation.
5110 Notes
5111 -----
5112 The mask is lost if `out` is not a valid :class:`MaskedArray` !
5114 Arithmetic is modular when using integer types, and no error is
5115 raised on overflow.
5117 See Also
5118 --------
5119 numpy.ndarray.cumsum : corresponding function for ndarrays
5120 numpy.cumsum : equivalent function
5122 Examples
5123 --------
5124 >>> marr = np.ma.array(np.arange(10), mask=[0,0,0,1,1,1,0,0,0,0])
5125 >>> marr.cumsum()
5126 masked_array(data=[0, 1, 3, --, --, --, 9, 16, 24, 33],
5127 mask=[False, False, False, True, True, True, False, False,
5128 False, False],
5129 fill_value=999999)
5131 """
5132 result = self.filled(0).cumsum(axis=axis, dtype=dtype, out=out)
5133 if out is not None:
5134 if isinstance(out, MaskedArray):
5135 out.__setmask__(self.mask)
5136 return out
5137 result = result.view(type(self))
5138 result.__setmask__(self._mask)
5139 return result
5141 def prod(self, axis=None, dtype=None, out=None, keepdims=np._NoValue):
5142 """
5143 Return the product of the array elements over the given axis.
5145 Masked elements are set to 1 internally for computation.
5147 Refer to `numpy.prod` for full documentation.
5149 Notes
5150 -----
5151 Arithmetic is modular when using integer types, and no error is raised
5152 on overflow.
5154 See Also
5155 --------
5156 numpy.ndarray.prod : corresponding function for ndarrays
5157 numpy.prod : equivalent function
5158 """
5159 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims}
5161 _mask = self._mask
5162 newmask = _check_mask_axis(_mask, axis, **kwargs)
5163 # No explicit output
5164 if out is None:
5165 result = self.filled(1).prod(axis, dtype=dtype, **kwargs)
5166 rndim = getattr(result, 'ndim', 0)
5167 if rndim:
5168 result = result.view(type(self))
5169 result.__setmask__(newmask)
5170 elif newmask:
5171 result = masked
5172 return result
5173 # Explicit output
5174 result = self.filled(1).prod(axis, dtype=dtype, out=out, **kwargs)
5175 if isinstance(out, MaskedArray):
5176 outmask = getmask(out)
5177 if outmask is nomask:
5178 outmask = out._mask = make_mask_none(out.shape)
5179 outmask.flat = newmask
5180 return out
5181 product = prod
5183 def cumprod(self, axis=None, dtype=None, out=None):
5184 """
5185 Return the cumulative product of the array elements over the given axis.
5187 Masked values are set to 1 internally during the computation.
5188 However, their position is saved, and the result will be masked at
5189 the same locations.
5191 Refer to `numpy.cumprod` for full documentation.
5193 Notes
5194 -----
5195 The mask is lost if `out` is not a valid MaskedArray !
5197 Arithmetic is modular when using integer types, and no error is
5198 raised on overflow.
5200 See Also
5201 --------
5202 numpy.ndarray.cumprod : corresponding function for ndarrays
5203 numpy.cumprod : equivalent function
5204 """
5205 result = self.filled(1).cumprod(axis=axis, dtype=dtype, out=out)
5206 if out is not None:
5207 if isinstance(out, MaskedArray):
5208 out.__setmask__(self._mask)
5209 return out
5210 result = result.view(type(self))
5211 result.__setmask__(self._mask)
5212 return result
5214 def mean(self, axis=None, dtype=None, out=None, keepdims=np._NoValue):
5215 """
5216 Returns the average of the array elements along given axis.
5218 Masked entries are ignored, and result elements which are not
5219 finite will be masked.
5221 Refer to `numpy.mean` for full documentation.
5223 See Also
5224 --------
5225 numpy.ndarray.mean : corresponding function for ndarrays
5226 numpy.mean : Equivalent function
5227 numpy.ma.average: Weighted average.
5229 Examples
5230 --------
5231 >>> a = np.ma.array([1,2,3], mask=[False, False, True])
5232 >>> a
5233 masked_array(data=[1, 2, --],
5234 mask=[False, False, True],
5235 fill_value=999999)
5236 >>> a.mean()
5237 1.5
5239 """
5240 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims}
5242 if self._mask is nomask:
5243 result = super(MaskedArray, self).mean(axis=axis,
5244 dtype=dtype, **kwargs)[()]
5245 else:
5246 dsum = self.sum(axis=axis, dtype=dtype, **kwargs)
5247 cnt = self.count(axis=axis, **kwargs)
5248 if cnt.shape == () and (cnt == 0):
5249 result = masked
5250 else:
5251 result = dsum * 1. / cnt
5252 if out is not None:
5253 out.flat = result
5254 if isinstance(out, MaskedArray):
5255 outmask = getmask(out)
5256 if outmask is nomask:
5257 outmask = out._mask = make_mask_none(out.shape)
5258 outmask.flat = getmask(result)
5259 return out
5260 return result
5262 def anom(self, axis=None, dtype=None):
5263 """
5264 Compute the anomalies (deviations from the arithmetic mean)
5265 along the given axis.
5267 Returns an array of anomalies, with the same shape as the input and
5268 where the arithmetic mean is computed along the given axis.
5270 Parameters
5271 ----------
5272 axis : int, optional
5273 Axis over which the anomalies are taken.
5274 The default is to use the mean of the flattened array as reference.
5275 dtype : dtype, optional
5276 Type to use in computing the variance. For arrays of integer type
5277 the default is float32; for arrays of float types it is the same as
5278 the array type.
5280 See Also
5281 --------
5282 mean : Compute the mean of the array.
5284 Examples
5285 --------
5286 >>> a = np.ma.array([1,2,3])
5287 >>> a.anom()
5288 masked_array(data=[-1., 0., 1.],
5289 mask=False,
5290 fill_value=1e+20)
5292 """
5293 m = self.mean(axis, dtype)
5294 if m is masked:
5295 return m
5297 if not axis:
5298 return self - m
5299 else:
5300 return self - expand_dims(m, axis)
5302 def var(self, axis=None, dtype=None, out=None, ddof=0,
5303 keepdims=np._NoValue):
5304 """
5305 Returns the variance of the array elements along given axis.
5307 Masked entries are ignored, and result elements which are not
5308 finite will be masked.
5310 Refer to `numpy.var` for full documentation.
5312 See Also
5313 --------
5314 numpy.ndarray.var : corresponding function for ndarrays
5315 numpy.var : Equivalent function
5316 """
5317 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims}
5319 # Easy case: nomask, business as usual
5320 if self._mask is nomask:
5321 ret = super(MaskedArray, self).var(axis=axis, dtype=dtype, out=out,
5322 ddof=ddof, **kwargs)[()]
5323 if out is not None:
5324 if isinstance(out, MaskedArray):
5325 out.__setmask__(nomask)
5326 return out
5327 return ret
5329 # Some data are masked, yay!
5330 cnt = self.count(axis=axis, **kwargs) - ddof
5331 danom = self - self.mean(axis, dtype, keepdims=True)
5332 if iscomplexobj(self):
5333 danom = umath.absolute(danom) ** 2
5334 else:
5335 danom *= danom
5336 dvar = divide(danom.sum(axis, **kwargs), cnt).view(type(self))
5337 # Apply the mask if it's not a scalar
5338 if dvar.ndim:
5339 dvar._mask = mask_or(self._mask.all(axis, **kwargs), (cnt <= 0))
5340 dvar._update_from(self)
5341 elif getmask(dvar):
5342 # Make sure that masked is returned when the scalar is masked.
5343 dvar = masked
5344 if out is not None:
5345 if isinstance(out, MaskedArray):
5346 out.flat = 0
5347 out.__setmask__(True)
5348 elif out.dtype.kind in 'biu':
5349 errmsg = "Masked data information would be lost in one or "\
5350 "more location."
5351 raise MaskError(errmsg)
5352 else:
5353 out.flat = np.nan
5354 return out
5355 # In case with have an explicit output
5356 if out is not None:
5357 # Set the data
5358 out.flat = dvar
5359 # Set the mask if needed
5360 if isinstance(out, MaskedArray):
5361 out.__setmask__(dvar.mask)
5362 return out
5363 return dvar
5364 var.__doc__ = np.var.__doc__
5366 def std(self, axis=None, dtype=None, out=None, ddof=0,
5367 keepdims=np._NoValue):
5368 """
5369 Returns the standard deviation of the array elements along given axis.
5371 Masked entries are ignored.
5373 Refer to `numpy.std` for full documentation.
5375 See Also
5376 --------
5377 numpy.ndarray.std : corresponding function for ndarrays
5378 numpy.std : Equivalent function
5379 """
5380 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims}
5382 dvar = self.var(axis, dtype, out, ddof, **kwargs)
5383 if dvar is not masked:
5384 if out is not None:
5385 np.power(out, 0.5, out=out, casting='unsafe')
5386 return out
5387 dvar = sqrt(dvar)
5388 return dvar
5390 def round(self, decimals=0, out=None):
5391 """
5392 Return each element rounded to the given number of decimals.
5394 Refer to `numpy.around` for full documentation.
5396 See Also
5397 --------
5398 numpy.ndarray.around : corresponding function for ndarrays
5399 numpy.around : equivalent function
5400 """
5401 result = self._data.round(decimals=decimals, out=out).view(type(self))
5402 if result.ndim > 0:
5403 result._mask = self._mask
5404 result._update_from(self)
5405 elif self._mask:
5406 # Return masked when the scalar is masked
5407 result = masked
5408 # No explicit output: we're done
5409 if out is None:
5410 return result
5411 if isinstance(out, MaskedArray):
5412 out.__setmask__(self._mask)
5413 return out
5415 def argsort(self, axis=np._NoValue, kind=None, order=None,
5416 endwith=True, fill_value=None):
5417 """
5418 Return an ndarray of indices that sort the array along the
5419 specified axis. Masked values are filled beforehand to
5420 `fill_value`.
5422 Parameters
5423 ----------
5424 axis : int, optional
5425 Axis along which to sort. If None, the default, the flattened array
5426 is used.
5428 .. versionchanged:: 1.13.0
5429 Previously, the default was documented to be -1, but that was
5430 in error. At some future date, the default will change to -1, as
5431 originally intended.
5432 Until then, the axis should be given explicitly when
5433 ``arr.ndim > 1``, to avoid a FutureWarning.
5434 kind : {'quicksort', 'mergesort', 'heapsort', 'stable'}, optional
5435 The sorting algorithm used.
5436 order : list, optional
5437 When `a` is an array with fields defined, this argument specifies
5438 which fields to compare first, second, etc. Not all fields need be
5439 specified.
5440 endwith : {True, False}, optional
5441 Whether missing values (if any) should be treated as the largest values
5442 (True) or the smallest values (False)
5443 When the array contains unmasked values at the same extremes of the
5444 datatype, the ordering of these values and the masked values is
5445 undefined.
5446 fill_value : {var}, optional
5447 Value used internally for the masked values.
5448 If ``fill_value`` is not None, it supersedes ``endwith``.
5450 Returns
5451 -------
5452 index_array : ndarray, int
5453 Array of indices that sort `a` along the specified axis.
5454 In other words, ``a[index_array]`` yields a sorted `a`.
5456 See Also
5457 --------
5458 MaskedArray.sort : Describes sorting algorithms used.
5459 lexsort : Indirect stable sort with multiple keys.
5460 numpy.ndarray.sort : Inplace sort.
5462 Notes
5463 -----
5464 See `sort` for notes on the different sorting algorithms.
5466 Examples
5467 --------
5468 >>> a = np.ma.array([3,2,1], mask=[False, False, True])
5469 >>> a
5470 masked_array(data=[3, 2, --],
5471 mask=[False, False, True],
5472 fill_value=999999)
5473 >>> a.argsort()
5474 array([1, 0, 2])
5476 """
5478 # 2017-04-11, Numpy 1.13.0, gh-8701: warn on axis default
5479 if axis is np._NoValue:
5480 axis = _deprecate_argsort_axis(self)
5482 if fill_value is None:
5483 if endwith:
5484 # nan > inf
5485 if np.issubdtype(self.dtype, np.floating):
5486 fill_value = np.nan
5487 else:
5488 fill_value = minimum_fill_value(self)
5489 else:
5490 fill_value = maximum_fill_value(self)
5492 filled = self.filled(fill_value)
5493 return filled.argsort(axis=axis, kind=kind, order=order)
5495 def argmin(self, axis=None, fill_value=None, out=None):
5496 """
5497 Return array of indices to the minimum values along the given axis.
5499 Parameters
5500 ----------
5501 axis : {None, integer}
5502 If None, the index is into the flattened array, otherwise along
5503 the specified axis
5504 fill_value : {var}, optional
5505 Value used to fill in the masked values. If None, the output of
5506 minimum_fill_value(self._data) is used instead.
5507 out : {None, array}, optional
5508 Array into which the result can be placed. Its type is preserved
5509 and it must be of the right shape to hold the output.
5511 Returns
5512 -------
5513 ndarray or scalar
5514 If multi-dimension input, returns a new ndarray of indices to the
5515 minimum values along the given axis. Otherwise, returns a scalar
5516 of index to the minimum values along the given axis.
5518 Examples
5519 --------
5520 >>> x = np.ma.array(np.arange(4), mask=[1,1,0,0])
5521 >>> x.shape = (2,2)
5522 >>> x
5523 masked_array(
5524 data=[[--, --],
5525 [2, 3]],
5526 mask=[[ True, True],
5527 [False, False]],
5528 fill_value=999999)
5529 >>> x.argmin(axis=0, fill_value=-1)
5530 array([0, 0])
5531 >>> x.argmin(axis=0, fill_value=9)
5532 array([1, 1])
5534 """
5535 if fill_value is None:
5536 fill_value = minimum_fill_value(self)
5537 d = self.filled(fill_value).view(ndarray)
5538 return d.argmin(axis, out=out)
5540 def argmax(self, axis=None, fill_value=None, out=None):
5541 """
5542 Returns array of indices of the maximum values along the given axis.
5543 Masked values are treated as if they had the value fill_value.
5545 Parameters
5546 ----------
5547 axis : {None, integer}
5548 If None, the index is into the flattened array, otherwise along
5549 the specified axis
5550 fill_value : {var}, optional
5551 Value used to fill in the masked values. If None, the output of
5552 maximum_fill_value(self._data) is used instead.
5553 out : {None, array}, optional
5554 Array into which the result can be placed. Its type is preserved
5555 and it must be of the right shape to hold the output.
5557 Returns
5558 -------
5559 index_array : {integer_array}
5561 Examples
5562 --------
5563 >>> a = np.arange(6).reshape(2,3)
5564 >>> a.argmax()
5565 5
5566 >>> a.argmax(0)
5567 array([1, 1, 1])
5568 >>> a.argmax(1)
5569 array([2, 2])
5571 """
5572 if fill_value is None:
5573 fill_value = maximum_fill_value(self._data)
5574 d = self.filled(fill_value).view(ndarray)
5575 return d.argmax(axis, out=out)
5577 def sort(self, axis=-1, kind=None, order=None,
5578 endwith=True, fill_value=None):
5579 """
5580 Sort the array, in-place
5582 Parameters
5583 ----------
5584 a : array_like
5585 Array to be sorted.
5586 axis : int, optional
5587 Axis along which to sort. If None, the array is flattened before
5588 sorting. The default is -1, which sorts along the last axis.
5589 kind : {'quicksort', 'mergesort', 'heapsort', 'stable'}, optional
5590 The sorting algorithm used.
5591 order : list, optional
5592 When `a` is a structured array, this argument specifies which fields
5593 to compare first, second, and so on. This list does not need to
5594 include all of the fields.
5595 endwith : {True, False}, optional
5596 Whether missing values (if any) should be treated as the largest values
5597 (True) or the smallest values (False)
5598 When the array contains unmasked values sorting at the same extremes of the
5599 datatype, the ordering of these values and the masked values is
5600 undefined.
5601 fill_value : {var}, optional
5602 Value used internally for the masked values.
5603 If ``fill_value`` is not None, it supersedes ``endwith``.
5605 Returns
5606 -------
5607 sorted_array : ndarray
5608 Array of the same type and shape as `a`.
5610 See Also
5611 --------
5612 numpy.ndarray.sort : Method to sort an array in-place.
5613 argsort : Indirect sort.
5614 lexsort : Indirect stable sort on multiple keys.
5615 searchsorted : Find elements in a sorted array.
5617 Notes
5618 -----
5619 See ``sort`` for notes on the different sorting algorithms.
5621 Examples
5622 --------
5623 >>> a = np.ma.array([1, 2, 5, 4, 3],mask=[0, 1, 0, 1, 0])
5624 >>> # Default
5625 >>> a.sort()
5626 >>> a
5627 masked_array(data=[1, 3, 5, --, --],
5628 mask=[False, False, False, True, True],
5629 fill_value=999999)
5631 >>> a = np.ma.array([1, 2, 5, 4, 3],mask=[0, 1, 0, 1, 0])
5632 >>> # Put missing values in the front
5633 >>> a.sort(endwith=False)
5634 >>> a
5635 masked_array(data=[--, --, 1, 3, 5],
5636 mask=[ True, True, False, False, False],
5637 fill_value=999999)
5639 >>> a = np.ma.array([1, 2, 5, 4, 3],mask=[0, 1, 0, 1, 0])
5640 >>> # fill_value takes over endwith
5641 >>> a.sort(endwith=False, fill_value=3)
5642 >>> a
5643 masked_array(data=[1, --, --, 3, 5],
5644 mask=[False, True, True, False, False],
5645 fill_value=999999)
5647 """
5648 if self._mask is nomask:
5649 ndarray.sort(self, axis=axis, kind=kind, order=order)
5650 return
5652 if self is masked:
5653 return
5655 sidx = self.argsort(axis=axis, kind=kind, order=order,
5656 fill_value=fill_value, endwith=endwith)
5658 self[...] = np.take_along_axis(self, sidx, axis=axis)
5660 def min(self, axis=None, out=None, fill_value=None, keepdims=np._NoValue):
5661 """
5662 Return the minimum along a given axis.
5664 Parameters
5665 ----------
5666 axis : {None, int}, optional
5667 Axis along which to operate. By default, ``axis`` is None and the
5668 flattened input is used.
5669 out : array_like, optional
5670 Alternative output array in which to place the result. Must be of
5671 the same shape and buffer length as the expected output.
5672 fill_value : {var}, optional
5673 Value used to fill in the masked values.
5674 If None, use the output of `minimum_fill_value`.
5675 keepdims : bool, optional
5676 If this is set to True, the axes which are reduced are left
5677 in the result as dimensions with size one. With this option,
5678 the result will broadcast correctly against the array.
5680 Returns
5681 -------
5682 amin : array_like
5683 New array holding the result.
5684 If ``out`` was specified, ``out`` is returned.
5686 See Also
5687 --------
5688 minimum_fill_value
5689 Returns the minimum filling value for a given datatype.
5691 """
5692 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims}
5694 _mask = self._mask
5695 newmask = _check_mask_axis(_mask, axis, **kwargs)
5696 if fill_value is None:
5697 fill_value = minimum_fill_value(self)
5698 # No explicit output
5699 if out is None:
5700 result = self.filled(fill_value).min(
5701 axis=axis, out=out, **kwargs).view(type(self))
5702 if result.ndim:
5703 # Set the mask
5704 result.__setmask__(newmask)
5705 # Get rid of Infs
5706 if newmask.ndim:
5707 np.copyto(result, result.fill_value, where=newmask)
5708 elif newmask:
5709 result = masked
5710 return result
5711 # Explicit output
5712 result = self.filled(fill_value).min(axis=axis, out=out, **kwargs)
5713 if isinstance(out, MaskedArray):
5714 outmask = getmask(out)
5715 if outmask is nomask:
5716 outmask = out._mask = make_mask_none(out.shape)
5717 outmask.flat = newmask
5718 else:
5719 if out.dtype.kind in 'biu':
5720 errmsg = "Masked data information would be lost in one or more"\
5721 " location."
5722 raise MaskError(errmsg)
5723 np.copyto(out, np.nan, where=newmask)
5724 return out
5726 # unique to masked arrays
5727 def mini(self, axis=None):
5728 """
5729 Return the array minimum along the specified axis.
5731 .. deprecated:: 1.13.0
5732 This function is identical to both:
5734 * ``self.min(keepdims=True, axis=axis).squeeze(axis=axis)``
5735 * ``np.ma.minimum.reduce(self, axis=axis)``
5737 Typically though, ``self.min(axis=axis)`` is sufficient.
5739 Parameters
5740 ----------
5741 axis : int, optional
5742 The axis along which to find the minima. Default is None, in which case
5743 the minimum value in the whole array is returned.
5745 Returns
5746 -------
5747 min : scalar or MaskedArray
5748 If `axis` is None, the result is a scalar. Otherwise, if `axis` is
5749 given and the array is at least 2-D, the result is a masked array with
5750 dimension one smaller than the array on which `mini` is called.
5752 Examples
5753 --------
5754 >>> x = np.ma.array(np.arange(6), mask=[0 ,1, 0, 0, 0 ,1]).reshape(3, 2)
5755 >>> x
5756 masked_array(
5757 data=[[0, --],
5758 [2, 3],
5759 [4, --]],
5760 mask=[[False, True],
5761 [False, False],
5762 [False, True]],
5763 fill_value=999999)
5764 >>> x.mini()
5765 masked_array(data=0,
5766 mask=False,
5767 fill_value=999999)
5768 >>> x.mini(axis=0)
5769 masked_array(data=[0, 3],
5770 mask=[False, False],
5771 fill_value=999999)
5772 >>> x.mini(axis=1)
5773 masked_array(data=[0, 2, 4],
5774 mask=[False, False, False],
5775 fill_value=999999)
5777 There is a small difference between `mini` and `min`:
5779 >>> x[:,1].mini(axis=0)
5780 masked_array(data=3,
5781 mask=False,
5782 fill_value=999999)
5783 >>> x[:,1].min(axis=0)
5784 3
5785 """
5787 # 2016-04-13, 1.13.0, gh-8764
5788 warnings.warn(
5789 "`mini` is deprecated; use the `min` method or "
5790 "`np.ma.minimum.reduce instead.",
5791 DeprecationWarning, stacklevel=2)
5792 return minimum.reduce(self, axis)
5794 def max(self, axis=None, out=None, fill_value=None, keepdims=np._NoValue):
5795 """
5796 Return the maximum along a given axis.
5798 Parameters
5799 ----------
5800 axis : {None, int}, optional
5801 Axis along which to operate. By default, ``axis`` is None and the
5802 flattened input is used.
5803 out : array_like, optional
5804 Alternative output array in which to place the result. Must
5805 be of the same shape and buffer length as the expected output.
5806 fill_value : {var}, optional
5807 Value used to fill in the masked values.
5808 If None, use the output of maximum_fill_value().
5809 keepdims : bool, optional
5810 If this is set to True, the axes which are reduced are left
5811 in the result as dimensions with size one. With this option,
5812 the result will broadcast correctly against the array.
5814 Returns
5815 -------
5816 amax : array_like
5817 New array holding the result.
5818 If ``out`` was specified, ``out`` is returned.
5820 See Also
5821 --------
5822 maximum_fill_value
5823 Returns the maximum filling value for a given datatype.
5825 """
5826 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims}
5828 _mask = self._mask
5829 newmask = _check_mask_axis(_mask, axis, **kwargs)
5830 if fill_value is None:
5831 fill_value = maximum_fill_value(self)
5832 # No explicit output
5833 if out is None:
5834 result = self.filled(fill_value).max(
5835 axis=axis, out=out, **kwargs).view(type(self))
5836 if result.ndim:
5837 # Set the mask
5838 result.__setmask__(newmask)
5839 # Get rid of Infs
5840 if newmask.ndim:
5841 np.copyto(result, result.fill_value, where=newmask)
5842 elif newmask:
5843 result = masked
5844 return result
5845 # Explicit output
5846 result = self.filled(fill_value).max(axis=axis, out=out, **kwargs)
5847 if isinstance(out, MaskedArray):
5848 outmask = getmask(out)
5849 if outmask is nomask:
5850 outmask = out._mask = make_mask_none(out.shape)
5851 outmask.flat = newmask
5852 else:
5854 if out.dtype.kind in 'biu':
5855 errmsg = "Masked data information would be lost in one or more"\
5856 " location."
5857 raise MaskError(errmsg)
5858 np.copyto(out, np.nan, where=newmask)
5859 return out
5861 def ptp(self, axis=None, out=None, fill_value=None, keepdims=False):
5862 """
5863 Return (maximum - minimum) along the given dimension
5864 (i.e. peak-to-peak value).
5866 .. warning::
5867 `ptp` preserves the data type of the array. This means the
5868 return value for an input of signed integers with n bits
5869 (e.g. `np.int8`, `np.int16`, etc) is also a signed integer
5870 with n bits. In that case, peak-to-peak values greater than
5871 ``2**(n-1)-1`` will be returned as negative values. An example
5872 with a work-around is shown below.
5874 Parameters
5875 ----------
5876 axis : {None, int}, optional
5877 Axis along which to find the peaks. If None (default) the
5878 flattened array is used.
5879 out : {None, array_like}, optional
5880 Alternative output array in which to place the result. It must
5881 have the same shape and buffer length as the expected output
5882 but the type will be cast if necessary.
5883 fill_value : {var}, optional
5884 Value used to fill in the masked values.
5885 keepdims : bool, optional
5886 If this is set to True, the axes which are reduced are left
5887 in the result as dimensions with size one. With this option,
5888 the result will broadcast correctly against the array.
5890 Returns
5891 -------
5892 ptp : ndarray.
5893 A new array holding the result, unless ``out`` was
5894 specified, in which case a reference to ``out`` is returned.
5896 Examples
5897 --------
5898 >>> x = np.ma.MaskedArray([[4, 9, 2, 10],
5899 ... [6, 9, 7, 12]])
5901 >>> x.ptp(axis=1)
5902 masked_array(data=[8, 6],
5903 mask=False,
5904 fill_value=999999)
5906 >>> x.ptp(axis=0)
5907 masked_array(data=[2, 0, 5, 2],
5908 mask=False,
5909 fill_value=999999)
5911 >>> x.ptp()
5912 10
5914 This example shows that a negative value can be returned when
5915 the input is an array of signed integers.
5917 >>> y = np.ma.MaskedArray([[1, 127],
5918 ... [0, 127],
5919 ... [-1, 127],
5920 ... [-2, 127]], dtype=np.int8)
5921 >>> y.ptp(axis=1)
5922 masked_array(data=[ 126, 127, -128, -127],
5923 mask=False,
5924 fill_value=999999,
5925 dtype=int8)
5927 A work-around is to use the `view()` method to view the result as
5928 unsigned integers with the same bit width:
5930 >>> y.ptp(axis=1).view(np.uint8)
5931 masked_array(data=[126, 127, 128, 129],
5932 mask=False,
5933 fill_value=999999,
5934 dtype=uint8)
5935 """
5936 if out is None:
5937 result = self.max(axis=axis, fill_value=fill_value,
5938 keepdims=keepdims)
5939 result -= self.min(axis=axis, fill_value=fill_value,
5940 keepdims=keepdims)
5941 return result
5942 out.flat = self.max(axis=axis, out=out, fill_value=fill_value,
5943 keepdims=keepdims)
5944 min_value = self.min(axis=axis, fill_value=fill_value,
5945 keepdims=keepdims)
5946 np.subtract(out, min_value, out=out, casting='unsafe')
5947 return out
5949 def partition(self, *args, **kwargs):
5950 warnings.warn("Warning: 'partition' will ignore the 'mask' "
5951 f"of the {self.__class__.__name__}.",
5952 stacklevel=2)
5953 return super(MaskedArray, self).partition(*args, **kwargs)
5955 def argpartition(self, *args, **kwargs):
5956 warnings.warn("Warning: 'argpartition' will ignore the 'mask' "
5957 f"of the {self.__class__.__name__}.",
5958 stacklevel=2)
5959 return super(MaskedArray, self).argpartition(*args, **kwargs)
5961 def take(self, indices, axis=None, out=None, mode='raise'):
5962 """
5963 """
5964 (_data, _mask) = (self._data, self._mask)
5965 cls = type(self)
5966 # Make sure the indices are not masked
5967 maskindices = getmask(indices)
5968 if maskindices is not nomask:
5969 indices = indices.filled(0)
5970 # Get the data, promoting scalars to 0d arrays with [...] so that
5971 # .view works correctly
5972 if out is None:
5973 out = _data.take(indices, axis=axis, mode=mode)[...].view(cls)
5974 else:
5975 np.take(_data, indices, axis=axis, mode=mode, out=out)
5976 # Get the mask
5977 if isinstance(out, MaskedArray):
5978 if _mask is nomask:
5979 outmask = maskindices
5980 else:
5981 outmask = _mask.take(indices, axis=axis, mode=mode)
5982 outmask |= maskindices
5983 out.__setmask__(outmask)
5984 # demote 0d arrays back to scalars, for consistency with ndarray.take
5985 return out[()]
5987 # Array methods
5988 copy = _arraymethod('copy')
5989 diagonal = _arraymethod('diagonal')
5990 flatten = _arraymethod('flatten')
5991 repeat = _arraymethod('repeat')
5992 squeeze = _arraymethod('squeeze')
5993 swapaxes = _arraymethod('swapaxes')
5994 T = property(fget=lambda self: self.transpose())
5995 transpose = _arraymethod('transpose')
5997 def tolist(self, fill_value=None):
5998 """
5999 Return the data portion of the masked array as a hierarchical Python list.
6001 Data items are converted to the nearest compatible Python type.
6002 Masked values are converted to `fill_value`. If `fill_value` is None,
6003 the corresponding entries in the output list will be ``None``.
6005 Parameters
6006 ----------
6007 fill_value : scalar, optional
6008 The value to use for invalid entries. Default is None.
6010 Returns
6011 -------
6012 result : list
6013 The Python list representation of the masked array.
6015 Examples
6016 --------
6017 >>> x = np.ma.array([[1,2,3], [4,5,6], [7,8,9]], mask=[0] + [1,0]*4)
6018 >>> x.tolist()
6019 [[1, None, 3], [None, 5, None], [7, None, 9]]
6020 >>> x.tolist(-999)
6021 [[1, -999, 3], [-999, 5, -999], [7, -999, 9]]
6023 """
6024 _mask = self._mask
6025 # No mask ? Just return .data.tolist ?
6026 if _mask is nomask:
6027 return self._data.tolist()
6028 # Explicit fill_value: fill the array and get the list
6029 if fill_value is not None:
6030 return self.filled(fill_value).tolist()
6031 # Structured array.
6032 names = self.dtype.names
6033 if names:
6034 result = self._data.astype([(_, object) for _ in names])
6035 for n in names:
6036 result[n][_mask[n]] = None
6037 return result.tolist()
6038 # Standard arrays.
6039 if _mask is nomask:
6040 return [None]
6041 # Set temps to save time when dealing w/ marrays.
6042 inishape = self.shape
6043 result = np.array(self._data.ravel(), dtype=object)
6044 result[_mask.ravel()] = None
6045 result.shape = inishape
6046 return result.tolist()
6048 def tostring(self, fill_value=None, order='C'):
6049 r"""
6050 A compatibility alias for `tobytes`, with exactly the same behavior.
6052 Despite its name, it returns `bytes` not `str`\ s.
6054 .. deprecated:: 1.19.0
6055 """
6056 # 2020-03-30, Numpy 1.19.0
6057 warnings.warn(
6058 "tostring() is deprecated. Use tobytes() instead.",
6059 DeprecationWarning, stacklevel=2)
6061 return self.tobytes(fill_value, order=order)
6063 def tobytes(self, fill_value=None, order='C'):
6064 """
6065 Return the array data as a string containing the raw bytes in the array.
6067 The array is filled with a fill value before the string conversion.
6069 .. versionadded:: 1.9.0
6071 Parameters
6072 ----------
6073 fill_value : scalar, optional
6074 Value used to fill in the masked values. Default is None, in which
6075 case `MaskedArray.fill_value` is used.
6076 order : {'C','F','A'}, optional
6077 Order of the data item in the copy. Default is 'C'.
6079 - 'C' -- C order (row major).
6080 - 'F' -- Fortran order (column major).
6081 - 'A' -- Any, current order of array.
6082 - None -- Same as 'A'.
6084 See Also
6085 --------
6086 numpy.ndarray.tobytes
6087 tolist, tofile
6089 Notes
6090 -----
6091 As for `ndarray.tobytes`, information about the shape, dtype, etc.,
6092 but also about `fill_value`, will be lost.
6094 Examples
6095 --------
6096 >>> x = np.ma.array(np.array([[1, 2], [3, 4]]), mask=[[0, 1], [1, 0]])
6097 >>> x.tobytes()
6098 b'\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00?B\\x0f\\x00\\x00\\x00\\x00\\x00?B\\x0f\\x00\\x00\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00'
6100 """
6101 return self.filled(fill_value).tobytes(order=order)
6103 def tofile(self, fid, sep="", format="%s"):
6104 """
6105 Save a masked array to a file in binary format.
6107 .. warning::
6108 This function is not implemented yet.
6110 Raises
6111 ------
6112 NotImplementedError
6113 When `tofile` is called.
6115 """
6116 raise NotImplementedError("MaskedArray.tofile() not implemented yet.")
6118 def toflex(self):
6119 """
6120 Transforms a masked array into a flexible-type array.
6122 The flexible type array that is returned will have two fields:
6124 * the ``_data`` field stores the ``_data`` part of the array.
6125 * the ``_mask`` field stores the ``_mask`` part of the array.
6127 Parameters
6128 ----------
6129 None
6131 Returns
6132 -------
6133 record : ndarray
6134 A new flexible-type `ndarray` with two fields: the first element
6135 containing a value, the second element containing the corresponding
6136 mask boolean. The returned record shape matches self.shape.
6138 Notes
6139 -----
6140 A side-effect of transforming a masked array into a flexible `ndarray` is
6141 that meta information (``fill_value``, ...) will be lost.
6143 Examples
6144 --------
6145 >>> x = np.ma.array([[1,2,3],[4,5,6],[7,8,9]], mask=[0] + [1,0]*4)
6146 >>> x
6147 masked_array(
6148 data=[[1, --, 3],
6149 [--, 5, --],
6150 [7, --, 9]],
6151 mask=[[False, True, False],
6152 [ True, False, True],
6153 [False, True, False]],
6154 fill_value=999999)
6155 >>> x.toflex()
6156 array([[(1, False), (2, True), (3, False)],
6157 [(4, True), (5, False), (6, True)],
6158 [(7, False), (8, True), (9, False)]],
6159 dtype=[('_data', '<i8'), ('_mask', '?')])
6161 """
6162 # Get the basic dtype.
6163 ddtype = self.dtype
6164 # Make sure we have a mask
6165 _mask = self._mask
6166 if _mask is None:
6167 _mask = make_mask_none(self.shape, ddtype)
6168 # And get its dtype
6169 mdtype = self._mask.dtype
6171 record = np.ndarray(shape=self.shape,
6172 dtype=[('_data', ddtype), ('_mask', mdtype)])
6173 record['_data'] = self._data
6174 record['_mask'] = self._mask
6175 return record
6176 torecords = toflex
6178 # Pickling
6179 def __getstate__(self):
6180 """Return the internal state of the masked array, for pickling
6181 purposes.
6183 """
6184 cf = 'CF'[self.flags.fnc]
6185 data_state = super(MaskedArray, self).__reduce__()[2]
6186 return data_state + (getmaskarray(self).tobytes(cf), self._fill_value)
6188 def __setstate__(self, state):
6189 """Restore the internal state of the masked array, for
6190 pickling purposes. ``state`` is typically the output of the
6191 ``__getstate__`` output, and is a 5-tuple:
6193 - class name
6194 - a tuple giving the shape of the data
6195 - a typecode for the data
6196 - a binary string for the data
6197 - a binary string for the mask.
6199 """
6200 (_, shp, typ, isf, raw, msk, flv) = state
6201 super(MaskedArray, self).__setstate__((shp, typ, isf, raw))
6202 self._mask.__setstate__((shp, make_mask_descr(typ), isf, msk))
6203 self.fill_value = flv
6205 def __reduce__(self):
6206 """Return a 3-tuple for pickling a MaskedArray.
6208 """
6209 return (_mareconstruct,
6210 (self.__class__, self._baseclass, (0,), 'b',),
6211 self.__getstate__())
6213 def __deepcopy__(self, memo=None):
6214 from copy import deepcopy
6215 copied = MaskedArray.__new__(type(self), self, copy=True)
6216 if memo is None:
6217 memo = {}
6218 memo[id(self)] = copied
6219 for (k, v) in self.__dict__.items():
6220 copied.__dict__[k] = deepcopy(v, memo)
6221 return copied
6224def _mareconstruct(subtype, baseclass, baseshape, basetype,):
6225 """Internal function that builds a new MaskedArray from the
6226 information stored in a pickle.
6228 """
6229 _data = ndarray.__new__(baseclass, baseshape, basetype)
6230 _mask = ndarray.__new__(ndarray, baseshape, make_mask_descr(basetype))
6231 return subtype.__new__(subtype, _data, mask=_mask, dtype=basetype,)
6234class mvoid(MaskedArray):
6235 """
6236 Fake a 'void' object to use for masked array with structured dtypes.
6237 """
6239 def __new__(self, data, mask=nomask, dtype=None, fill_value=None,
6240 hardmask=False, copy=False, subok=True):
6241 _data = np.array(data, copy=copy, subok=subok, dtype=dtype)
6242 _data = _data.view(self)
6243 _data._hardmask = hardmask
6244 if mask is not nomask:
6245 if isinstance(mask, np.void):
6246 _data._mask = mask
6247 else:
6248 try:
6249 # Mask is already a 0D array
6250 _data._mask = np.void(mask)
6251 except TypeError:
6252 # Transform the mask to a void
6253 mdtype = make_mask_descr(dtype)
6254 _data._mask = np.array(mask, dtype=mdtype)[()]
6255 if fill_value is not None:
6256 _data.fill_value = fill_value
6257 return _data
6259 @property
6260 def _data(self):
6261 # Make sure that the _data part is a np.void
6262 return super(mvoid, self)._data[()]
6264 def __getitem__(self, indx):
6265 """
6266 Get the index.
6268 """
6269 m = self._mask
6270 if isinstance(m[indx], ndarray):
6271 # Can happen when indx is a multi-dimensional field:
6272 # A = ma.masked_array(data=[([0,1],)], mask=[([True,
6273 # False],)], dtype=[("A", ">i2", (2,))])
6274 # x = A[0]; y = x["A"]; then y.mask["A"].size==2
6275 # and we can not say masked/unmasked.
6276 # The result is no longer mvoid!
6277 # See also issue #6724.
6278 return masked_array(
6279 data=self._data[indx], mask=m[indx],
6280 fill_value=self._fill_value[indx],
6281 hard_mask=self._hardmask)
6282 if m is not nomask and m[indx]:
6283 return masked
6284 return self._data[indx]
6286 def __setitem__(self, indx, value):
6287 self._data[indx] = value
6288 if self._hardmask:
6289 self._mask[indx] |= getattr(value, "_mask", False)
6290 else:
6291 self._mask[indx] = getattr(value, "_mask", False)
6293 def __str__(self):
6294 m = self._mask
6295 if m is nomask:
6296 return str(self._data)
6298 rdtype = _replace_dtype_fields(self._data.dtype, "O")
6299 data_arr = super(mvoid, self)._data
6300 res = data_arr.astype(rdtype)
6301 _recursive_printoption(res, self._mask, masked_print_option)
6302 return str(res)
6304 __repr__ = __str__
6306 def __iter__(self):
6307 "Defines an iterator for mvoid"
6308 (_data, _mask) = (self._data, self._mask)
6309 if _mask is nomask:
6310 yield from _data
6311 else:
6312 for (d, m) in zip(_data, _mask):
6313 if m:
6314 yield masked
6315 else:
6316 yield d
6318 def __len__(self):
6319 return self._data.__len__()
6321 def filled(self, fill_value=None):
6322 """
6323 Return a copy with masked fields filled with a given value.
6325 Parameters
6326 ----------
6327 fill_value : array_like, optional
6328 The value to use for invalid entries. Can be scalar or
6329 non-scalar. If latter is the case, the filled array should
6330 be broadcastable over input array. Default is None, in
6331 which case the `fill_value` attribute is used instead.
6333 Returns
6334 -------
6335 filled_void
6336 A `np.void` object
6338 See Also
6339 --------
6340 MaskedArray.filled
6342 """
6343 return asarray(self).filled(fill_value)[()]
6345 def tolist(self):
6346 """
6347 Transforms the mvoid object into a tuple.
6349 Masked fields are replaced by None.
6351 Returns
6352 -------
6353 returned_tuple
6354 Tuple of fields
6355 """
6356 _mask = self._mask
6357 if _mask is nomask:
6358 return self._data.tolist()
6359 result = []
6360 for (d, m) in zip(self._data, self._mask):
6361 if m:
6362 result.append(None)
6363 else:
6364 # .item() makes sure we return a standard Python object
6365 result.append(d.item())
6366 return tuple(result)
6369##############################################################################
6370# Shortcuts #
6371##############################################################################
6374def isMaskedArray(x):
6375 """
6376 Test whether input is an instance of MaskedArray.
6378 This function returns True if `x` is an instance of MaskedArray
6379 and returns False otherwise. Any object is accepted as input.
6381 Parameters
6382 ----------
6383 x : object
6384 Object to test.
6386 Returns
6387 -------
6388 result : bool
6389 True if `x` is a MaskedArray.
6391 See Also
6392 --------
6393 isMA : Alias to isMaskedArray.
6394 isarray : Alias to isMaskedArray.
6396 Examples
6397 --------
6398 >>> import numpy.ma as ma
6399 >>> a = np.eye(3, 3)
6400 >>> a
6401 array([[ 1., 0., 0.],
6402 [ 0., 1., 0.],
6403 [ 0., 0., 1.]])
6404 >>> m = ma.masked_values(a, 0)
6405 >>> m
6406 masked_array(
6407 data=[[1.0, --, --],
6408 [--, 1.0, --],
6409 [--, --, 1.0]],
6410 mask=[[False, True, True],
6411 [ True, False, True],
6412 [ True, True, False]],
6413 fill_value=0.0)
6414 >>> ma.isMaskedArray(a)
6415 False
6416 >>> ma.isMaskedArray(m)
6417 True
6418 >>> ma.isMaskedArray([0, 1, 2])
6419 False
6421 """
6422 return isinstance(x, MaskedArray)
6425isarray = isMaskedArray
6426isMA = isMaskedArray # backward compatibility
6429class MaskedConstant(MaskedArray):
6430 # the lone np.ma.masked instance
6431 __singleton = None
6433 @classmethod
6434 def __has_singleton(cls):
6435 # second case ensures `cls.__singleton` is not just a view on the
6436 # superclass singleton
6437 return cls.__singleton is not None and type(cls.__singleton) is cls
6439 def __new__(cls):
6440 if not cls.__has_singleton():
6441 # We define the masked singleton as a float for higher precedence.
6442 # Note that it can be tricky sometimes w/ type comparison
6443 data = np.array(0.)
6444 mask = np.array(True)
6446 # prevent any modifications
6447 data.flags.writeable = False
6448 mask.flags.writeable = False
6450 # don't fall back on MaskedArray.__new__(MaskedConstant), since
6451 # that might confuse it - this way, the construction is entirely
6452 # within our control
6453 cls.__singleton = MaskedArray(data, mask=mask).view(cls)
6455 return cls.__singleton
6457 def __array_finalize__(self, obj):
6458 if not self.__has_singleton():
6459 # this handles the `.view` in __new__, which we want to copy across
6460 # properties normally
6461 return super(MaskedConstant, self).__array_finalize__(obj)
6462 elif self is self.__singleton:
6463 # not clear how this can happen, play it safe
6464 pass
6465 else:
6466 # everywhere else, we want to downcast to MaskedArray, to prevent a
6467 # duplicate maskedconstant.
6468 self.__class__ = MaskedArray
6469 MaskedArray.__array_finalize__(self, obj)
6471 def __array_prepare__(self, obj, context=None):
6472 return self.view(MaskedArray).__array_prepare__(obj, context)
6474 def __array_wrap__(self, obj, context=None):
6475 return self.view(MaskedArray).__array_wrap__(obj, context)
6477 def __str__(self):
6478 return str(masked_print_option._display)
6480 def __repr__(self):
6481 if self is MaskedConstant.__singleton:
6482 return 'masked'
6483 else:
6484 # it's a subclass, or something is wrong, make it obvious
6485 return object.__repr__(self)
6487 def __format__(self, format_spec):
6488 # Replace ndarray.__format__ with the default, which supports no format characters.
6489 # Supporting format characters is unwise here, because we do not know what type
6490 # the user was expecting - better to not guess.
6491 try:
6492 return object.__format__(self, format_spec)
6493 except TypeError:
6494 # 2020-03-23, NumPy 1.19.0
6495 warnings.warn(
6496 "Format strings passed to MaskedConstant are ignored, but in future may "
6497 "error or produce different behavior",
6498 FutureWarning, stacklevel=2
6499 )
6500 return object.__format__(self, "")
6502 def __reduce__(self):
6503 """Override of MaskedArray's __reduce__.
6504 """
6505 return (self.__class__, ())
6507 # inplace operations have no effect. We have to override them to avoid
6508 # trying to modify the readonly data and mask arrays
6509 def __iop__(self, other):
6510 return self
6511 __iadd__ = \
6512 __isub__ = \
6513 __imul__ = \
6514 __ifloordiv__ = \
6515 __itruediv__ = \
6516 __ipow__ = \
6517 __iop__
6518 del __iop__ # don't leave this around
6520 def copy(self, *args, **kwargs):
6521 """ Copy is a no-op on the maskedconstant, as it is a scalar """
6522 # maskedconstant is a scalar, so copy doesn't need to copy. There's
6523 # precedent for this with `np.bool_` scalars.
6524 return self
6526 def __copy__(self):
6527 return self
6529 def __deepcopy__(self, memo):
6530 return self
6532 def __setattr__(self, attr, value):
6533 if not self.__has_singleton():
6534 # allow the singleton to be initialized
6535 return super(MaskedConstant, self).__setattr__(attr, value)
6536 elif self is self.__singleton:
6537 raise AttributeError(
6538 f"attributes of {self!r} are not writeable")
6539 else:
6540 # duplicate instance - we can end up here from __array_finalize__,
6541 # where we set the __class__ attribute
6542 return super(MaskedConstant, self).__setattr__(attr, value)
6545masked = masked_singleton = MaskedConstant()
6546masked_array = MaskedArray
6549def array(data, dtype=None, copy=False, order=None,
6550 mask=nomask, fill_value=None, keep_mask=True,
6551 hard_mask=False, shrink=True, subok=True, ndmin=0):
6552 """
6553 Shortcut to MaskedArray.
6555 The options are in a different order for convenience and backwards
6556 compatibility.
6558 """
6559 return MaskedArray(data, mask=mask, dtype=dtype, copy=copy,
6560 subok=subok, keep_mask=keep_mask,
6561 hard_mask=hard_mask, fill_value=fill_value,
6562 ndmin=ndmin, shrink=shrink, order=order)
6563array.__doc__ = masked_array.__doc__
6566def is_masked(x):
6567 """
6568 Determine whether input has masked values.
6570 Accepts any object as input, but always returns False unless the
6571 input is a MaskedArray containing masked values.
6573 Parameters
6574 ----------
6575 x : array_like
6576 Array to check for masked values.
6578 Returns
6579 -------
6580 result : bool
6581 True if `x` is a MaskedArray with masked values, False otherwise.
6583 Examples
6584 --------
6585 >>> import numpy.ma as ma
6586 >>> x = ma.masked_equal([0, 1, 0, 2, 3], 0)
6587 >>> x
6588 masked_array(data=[--, 1, --, 2, 3],
6589 mask=[ True, False, True, False, False],
6590 fill_value=0)
6591 >>> ma.is_masked(x)
6592 True
6593 >>> x = ma.masked_equal([0, 1, 0, 2, 3], 42)
6594 >>> x
6595 masked_array(data=[0, 1, 0, 2, 3],
6596 mask=False,
6597 fill_value=42)
6598 >>> ma.is_masked(x)
6599 False
6601 Always returns False if `x` isn't a MaskedArray.
6603 >>> x = [False, True, False]
6604 >>> ma.is_masked(x)
6605 False
6606 >>> x = 'a string'
6607 >>> ma.is_masked(x)
6608 False
6610 """
6611 m = getmask(x)
6612 if m is nomask:
6613 return False
6614 elif m.any():
6615 return True
6616 return False
6619##############################################################################
6620# Extrema functions #
6621##############################################################################
6624class _extrema_operation(_MaskedUFunc):
6625 """
6626 Generic class for maximum/minimum functions.
6628 .. note::
6629 This is the base class for `_maximum_operation` and
6630 `_minimum_operation`.
6632 """
6633 def __init__(self, ufunc, compare, fill_value):
6634 super(_extrema_operation, self).__init__(ufunc)
6635 self.compare = compare
6636 self.fill_value_func = fill_value
6638 def __call__(self, a, b=None):
6639 "Executes the call behavior."
6640 if b is None:
6641 # 2016-04-13, 1.13.0
6642 warnings.warn(
6643 f"Single-argument form of np.ma.{self.__name__} is deprecated. Use "
6644 f"np.ma.{self.__name__}.reduce instead.",
6645 DeprecationWarning, stacklevel=2)
6646 return self.reduce(a)
6647 return where(self.compare(a, b), a, b)
6649 def reduce(self, target, axis=np._NoValue):
6650 "Reduce target along the given axis."
6651 target = narray(target, copy=False, subok=True)
6652 m = getmask(target)
6654 if axis is np._NoValue and target.ndim > 1:
6655 # 2017-05-06, Numpy 1.13.0: warn on axis default
6656 warnings.warn(
6657 f"In the future the default for ma.{self.__name__}.reduce will be axis=0, "
6658 f"not the current None, to match np.{self.__name__}.reduce. "
6659 "Explicitly pass 0 or None to silence this warning.",
6660 MaskedArrayFutureWarning, stacklevel=2)
6661 axis = None
6663 if axis is not np._NoValue:
6664 kwargs = dict(axis=axis)
6665 else:
6666 kwargs = dict()
6668 if m is nomask:
6669 t = self.f.reduce(target, **kwargs)
6670 else:
6671 target = target.filled(
6672 self.fill_value_func(target)).view(type(target))
6673 t = self.f.reduce(target, **kwargs)
6674 m = umath.logical_and.reduce(m, **kwargs)
6675 if hasattr(t, '_mask'):
6676 t._mask = m
6677 elif m:
6678 t = masked
6679 return t
6681 def outer(self, a, b):
6682 "Return the function applied to the outer product of a and b."
6683 ma = getmask(a)
6684 mb = getmask(b)
6685 if ma is nomask and mb is nomask:
6686 m = nomask
6687 else:
6688 ma = getmaskarray(a)
6689 mb = getmaskarray(b)
6690 m = logical_or.outer(ma, mb)
6691 result = self.f.outer(filled(a), filled(b))
6692 if not isinstance(result, MaskedArray):
6693 result = result.view(MaskedArray)
6694 result._mask = m
6695 return result
6697def min(obj, axis=None, out=None, fill_value=None, keepdims=np._NoValue):
6698 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims}
6700 try:
6701 return obj.min(axis=axis, fill_value=fill_value, out=out, **kwargs)
6702 except (AttributeError, TypeError):
6703 # If obj doesn't have a min method, or if the method doesn't accept a
6704 # fill_value argument
6705 return asanyarray(obj).min(axis=axis, fill_value=fill_value,
6706 out=out, **kwargs)
6707min.__doc__ = MaskedArray.min.__doc__
6709def max(obj, axis=None, out=None, fill_value=None, keepdims=np._NoValue):
6710 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims}
6712 try:
6713 return obj.max(axis=axis, fill_value=fill_value, out=out, **kwargs)
6714 except (AttributeError, TypeError):
6715 # If obj doesn't have a max method, or if the method doesn't accept a
6716 # fill_value argument
6717 return asanyarray(obj).max(axis=axis, fill_value=fill_value,
6718 out=out, **kwargs)
6719max.__doc__ = MaskedArray.max.__doc__
6722def ptp(obj, axis=None, out=None, fill_value=None, keepdims=np._NoValue):
6723 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims}
6724 try:
6725 return obj.ptp(axis, out=out, fill_value=fill_value, **kwargs)
6726 except (AttributeError, TypeError):
6727 # If obj doesn't have a ptp method or if the method doesn't accept
6728 # a fill_value argument
6729 return asanyarray(obj).ptp(axis=axis, fill_value=fill_value,
6730 out=out, **kwargs)
6731ptp.__doc__ = MaskedArray.ptp.__doc__
6734##############################################################################
6735# Definition of functions from the corresponding methods #
6736##############################################################################
6739class _frommethod:
6740 """
6741 Define functions from existing MaskedArray methods.
6743 Parameters
6744 ----------
6745 methodname : str
6746 Name of the method to transform.
6748 """
6750 def __init__(self, methodname, reversed=False):
6751 self.__name__ = methodname
6752 self.__doc__ = self.getdoc()
6753 self.reversed = reversed
6755 def getdoc(self):
6756 "Return the doc of the function (from the doc of the method)."
6757 meth = getattr(MaskedArray, self.__name__, None) or\
6758 getattr(np, self.__name__, None)
6759 signature = self.__name__ + get_object_signature(meth)
6760 if meth is not None:
6761 doc = """ %s\n%s""" % (
6762 signature, getattr(meth, '__doc__', None))
6763 return doc
6765 def __call__(self, a, *args, **params):
6766 if self.reversed:
6767 args = list(args)
6768 a, args[0] = args[0], a
6770 marr = asanyarray(a)
6771 method_name = self.__name__
6772 method = getattr(type(marr), method_name, None)
6773 if method is None:
6774 # use the corresponding np function
6775 method = getattr(np, method_name)
6777 return method(marr, *args, **params)
6780all = _frommethod('all')
6781anomalies = anom = _frommethod('anom')
6782any = _frommethod('any')
6783compress = _frommethod('compress', reversed=True)
6784cumprod = _frommethod('cumprod')
6785cumsum = _frommethod('cumsum')
6786copy = _frommethod('copy')
6787diagonal = _frommethod('diagonal')
6788harden_mask = _frommethod('harden_mask')
6789ids = _frommethod('ids')
6790maximum = _extrema_operation(umath.maximum, greater, maximum_fill_value)
6791mean = _frommethod('mean')
6792minimum = _extrema_operation(umath.minimum, less, minimum_fill_value)
6793nonzero = _frommethod('nonzero')
6794prod = _frommethod('prod')
6795product = _frommethod('prod')
6796ravel = _frommethod('ravel')
6797repeat = _frommethod('repeat')
6798shrink_mask = _frommethod('shrink_mask')
6799soften_mask = _frommethod('soften_mask')
6800std = _frommethod('std')
6801sum = _frommethod('sum')
6802swapaxes = _frommethod('swapaxes')
6803#take = _frommethod('take')
6804trace = _frommethod('trace')
6805var = _frommethod('var')
6807count = _frommethod('count')
6809def take(a, indices, axis=None, out=None, mode='raise'):
6810 """
6811 """
6812 a = masked_array(a)
6813 return a.take(indices, axis=axis, out=out, mode=mode)
6816def power(a, b, third=None):
6817 """
6818 Returns element-wise base array raised to power from second array.
6820 This is the masked array version of `numpy.power`. For details see
6821 `numpy.power`.
6823 See Also
6824 --------
6825 numpy.power
6827 Notes
6828 -----
6829 The *out* argument to `numpy.power` is not supported, `third` has to be
6830 None.
6832 """
6833 if third is not None:
6834 raise MaskError("3-argument power not supported.")
6835 # Get the masks
6836 ma = getmask(a)
6837 mb = getmask(b)
6838 m = mask_or(ma, mb)
6839 # Get the rawdata
6840 fa = getdata(a)
6841 fb = getdata(b)
6842 # Get the type of the result (so that we preserve subclasses)
6843 if isinstance(a, MaskedArray):
6844 basetype = type(a)
6845 else:
6846 basetype = MaskedArray
6847 # Get the result and view it as a (subclass of) MaskedArray
6848 with np.errstate(divide='ignore', invalid='ignore'):
6849 result = np.where(m, fa, umath.power(fa, fb)).view(basetype)
6850 result._update_from(a)
6851 # Find where we're in trouble w/ NaNs and Infs
6852 invalid = np.logical_not(np.isfinite(result.view(ndarray)))
6853 # Add the initial mask
6854 if m is not nomask:
6855 if not result.ndim:
6856 return masked
6857 result._mask = np.logical_or(m, invalid)
6858 # Fix the invalid parts
6859 if invalid.any():
6860 if not result.ndim:
6861 return masked
6862 elif result._mask is nomask:
6863 result._mask = invalid
6864 result._data[invalid] = result.fill_value
6865 return result
6867argmin = _frommethod('argmin')
6868argmax = _frommethod('argmax')
6870def argsort(a, axis=np._NoValue, kind=None, order=None, endwith=True, fill_value=None):
6871 "Function version of the eponymous method."
6872 a = np.asanyarray(a)
6874 # 2017-04-11, Numpy 1.13.0, gh-8701: warn on axis default
6875 if axis is np._NoValue:
6876 axis = _deprecate_argsort_axis(a)
6878 if isinstance(a, MaskedArray):
6879 return a.argsort(axis=axis, kind=kind, order=order,
6880 endwith=endwith, fill_value=fill_value)
6881 else:
6882 return a.argsort(axis=axis, kind=kind, order=order)
6883argsort.__doc__ = MaskedArray.argsort.__doc__
6885def sort(a, axis=-1, kind=None, order=None, endwith=True, fill_value=None):
6886 """
6887 Return a sorted copy of the masked array.
6889 Equivalent to creating a copy of the array
6890 and applying the MaskedArray ``sort()`` method.
6892 Refer to ``MaskedArray.sort`` for the full documentation
6894 See Also
6895 --------
6896 MaskedArray.sort : equivalent method
6897 """
6898 a = np.array(a, copy=True, subok=True)
6899 if axis is None:
6900 a = a.flatten()
6901 axis = 0
6903 if isinstance(a, MaskedArray):
6904 a.sort(axis=axis, kind=kind, order=order,
6905 endwith=endwith, fill_value=fill_value)
6906 else:
6907 a.sort(axis=axis, kind=kind, order=order)
6908 return a
6911def compressed(x):
6912 """
6913 Return all the non-masked data as a 1-D array.
6915 This function is equivalent to calling the "compressed" method of a
6916 `MaskedArray`, see `MaskedArray.compressed` for details.
6918 See Also
6919 --------
6920 MaskedArray.compressed
6921 Equivalent method.
6923 """
6924 return asanyarray(x).compressed()
6927def concatenate(arrays, axis=0):
6928 """
6929 Concatenate a sequence of arrays along the given axis.
6931 Parameters
6932 ----------
6933 arrays : sequence of array_like
6934 The arrays must have the same shape, except in the dimension
6935 corresponding to `axis` (the first, by default).
6936 axis : int, optional
6937 The axis along which the arrays will be joined. Default is 0.
6939 Returns
6940 -------
6941 result : MaskedArray
6942 The concatenated array with any masked entries preserved.
6944 See Also
6945 --------
6946 numpy.concatenate : Equivalent function in the top-level NumPy module.
6948 Examples
6949 --------
6950 >>> import numpy.ma as ma
6951 >>> a = ma.arange(3)
6952 >>> a[1] = ma.masked
6953 >>> b = ma.arange(2, 5)
6954 >>> a
6955 masked_array(data=[0, --, 2],
6956 mask=[False, True, False],
6957 fill_value=999999)
6958 >>> b
6959 masked_array(data=[2, 3, 4],
6960 mask=False,
6961 fill_value=999999)
6962 >>> ma.concatenate([a, b])
6963 masked_array(data=[0, --, 2, 2, 3, 4],
6964 mask=[False, True, False, False, False, False],
6965 fill_value=999999)
6967 """
6968 d = np.concatenate([getdata(a) for a in arrays], axis)
6969 rcls = get_masked_subclass(*arrays)
6970 data = d.view(rcls)
6971 # Check whether one of the arrays has a non-empty mask.
6972 for x in arrays:
6973 if getmask(x) is not nomask:
6974 break
6975 else:
6976 return data
6977 # OK, so we have to concatenate the masks
6978 dm = np.concatenate([getmaskarray(a) for a in arrays], axis)
6979 dm = dm.reshape(d.shape)
6981 # If we decide to keep a '_shrinkmask' option, we want to check that
6982 # all of them are True, and then check for dm.any()
6983 data._mask = _shrink_mask(dm)
6984 return data
6987def diag(v, k=0):
6988 """
6989 Extract a diagonal or construct a diagonal array.
6991 This function is the equivalent of `numpy.diag` that takes masked
6992 values into account, see `numpy.diag` for details.
6994 See Also
6995 --------
6996 numpy.diag : Equivalent function for ndarrays.
6998 """
6999 output = np.diag(v, k).view(MaskedArray)
7000 if getmask(v) is not nomask:
7001 output._mask = np.diag(v._mask, k)
7002 return output
7005def left_shift(a, n):
7006 """
7007 Shift the bits of an integer to the left.
7009 This is the masked array version of `numpy.left_shift`, for details
7010 see that function.
7012 See Also
7013 --------
7014 numpy.left_shift
7016 """
7017 m = getmask(a)
7018 if m is nomask:
7019 d = umath.left_shift(filled(a), n)
7020 return masked_array(d)
7021 else:
7022 d = umath.left_shift(filled(a, 0), n)
7023 return masked_array(d, mask=m)
7026def right_shift(a, n):
7027 """
7028 Shift the bits of an integer to the right.
7030 This is the masked array version of `numpy.right_shift`, for details
7031 see that function.
7033 See Also
7034 --------
7035 numpy.right_shift
7037 """
7038 m = getmask(a)
7039 if m is nomask:
7040 d = umath.right_shift(filled(a), n)
7041 return masked_array(d)
7042 else:
7043 d = umath.right_shift(filled(a, 0), n)
7044 return masked_array(d, mask=m)
7047def put(a, indices, values, mode='raise'):
7048 """
7049 Set storage-indexed locations to corresponding values.
7051 This function is equivalent to `MaskedArray.put`, see that method
7052 for details.
7054 See Also
7055 --------
7056 MaskedArray.put
7058 """
7059 # We can't use 'frommethod', the order of arguments is different
7060 try:
7061 return a.put(indices, values, mode=mode)
7062 except AttributeError:
7063 return narray(a, copy=False).put(indices, values, mode=mode)
7066def putmask(a, mask, values): # , mode='raise'):
7067 """
7068 Changes elements of an array based on conditional and input values.
7070 This is the masked array version of `numpy.putmask`, for details see
7071 `numpy.putmask`.
7073 See Also
7074 --------
7075 numpy.putmask
7077 Notes
7078 -----
7079 Using a masked array as `values` will **not** transform a `ndarray` into
7080 a `MaskedArray`.
7082 """
7083 # We can't use 'frommethod', the order of arguments is different
7084 if not isinstance(a, MaskedArray):
7085 a = a.view(MaskedArray)
7086 (valdata, valmask) = (getdata(values), getmask(values))
7087 if getmask(a) is nomask:
7088 if valmask is not nomask:
7089 a._sharedmask = True
7090 a._mask = make_mask_none(a.shape, a.dtype)
7091 np.copyto(a._mask, valmask, where=mask)
7092 elif a._hardmask:
7093 if valmask is not nomask:
7094 m = a._mask.copy()
7095 np.copyto(m, valmask, where=mask)
7096 a.mask |= m
7097 else:
7098 if valmask is nomask:
7099 valmask = getmaskarray(values)
7100 np.copyto(a._mask, valmask, where=mask)
7101 np.copyto(a._data, valdata, where=mask)
7102 return
7105def transpose(a, axes=None):
7106 """
7107 Permute the dimensions of an array.
7109 This function is exactly equivalent to `numpy.transpose`.
7111 See Also
7112 --------
7113 numpy.transpose : Equivalent function in top-level NumPy module.
7115 Examples
7116 --------
7117 >>> import numpy.ma as ma
7118 >>> x = ma.arange(4).reshape((2,2))
7119 >>> x[1, 1] = ma.masked
7120 >>> x
7121 masked_array(
7122 data=[[0, 1],
7123 [2, --]],
7124 mask=[[False, False],
7125 [False, True]],
7126 fill_value=999999)
7128 >>> ma.transpose(x)
7129 masked_array(
7130 data=[[0, 2],
7131 [1, --]],
7132 mask=[[False, False],
7133 [False, True]],
7134 fill_value=999999)
7135 """
7136 # We can't use 'frommethod', as 'transpose' doesn't take keywords
7137 try:
7138 return a.transpose(axes)
7139 except AttributeError:
7140 return narray(a, copy=False).transpose(axes).view(MaskedArray)
7143def reshape(a, new_shape, order='C'):
7144 """
7145 Returns an array containing the same data with a new shape.
7147 Refer to `MaskedArray.reshape` for full documentation.
7149 See Also
7150 --------
7151 MaskedArray.reshape : equivalent function
7153 """
7154 # We can't use 'frommethod', it whine about some parameters. Dmmit.
7155 try:
7156 return a.reshape(new_shape, order=order)
7157 except AttributeError:
7158 _tmp = narray(a, copy=False).reshape(new_shape, order=order)
7159 return _tmp.view(MaskedArray)
7162def resize(x, new_shape):
7163 """
7164 Return a new masked array with the specified size and shape.
7166 This is the masked equivalent of the `numpy.resize` function. The new
7167 array is filled with repeated copies of `x` (in the order that the
7168 data are stored in memory). If `x` is masked, the new array will be
7169 masked, and the new mask will be a repetition of the old one.
7171 See Also
7172 --------
7173 numpy.resize : Equivalent function in the top level NumPy module.
7175 Examples
7176 --------
7177 >>> import numpy.ma as ma
7178 >>> a = ma.array([[1, 2] ,[3, 4]])
7179 >>> a[0, 1] = ma.masked
7180 >>> a
7181 masked_array(
7182 data=[[1, --],
7183 [3, 4]],
7184 mask=[[False, True],
7185 [False, False]],
7186 fill_value=999999)
7187 >>> np.resize(a, (3, 3))
7188 masked_array(
7189 data=[[1, 2, 3],
7190 [4, 1, 2],
7191 [3, 4, 1]],
7192 mask=False,
7193 fill_value=999999)
7194 >>> ma.resize(a, (3, 3))
7195 masked_array(
7196 data=[[1, --, 3],
7197 [4, 1, --],
7198 [3, 4, 1]],
7199 mask=[[False, True, False],
7200 [False, False, True],
7201 [False, False, False]],
7202 fill_value=999999)
7204 A MaskedArray is always returned, regardless of the input type.
7206 >>> a = np.array([[1, 2] ,[3, 4]])
7207 >>> ma.resize(a, (3, 3))
7208 masked_array(
7209 data=[[1, 2, 3],
7210 [4, 1, 2],
7211 [3, 4, 1]],
7212 mask=False,
7213 fill_value=999999)
7215 """
7216 # We can't use _frommethods here, as N.resize is notoriously whiny.
7217 m = getmask(x)
7218 if m is not nomask:
7219 m = np.resize(m, new_shape)
7220 result = np.resize(x, new_shape).view(get_masked_subclass(x))
7221 if result.ndim:
7222 result._mask = m
7223 return result
7226def ndim(obj):
7227 """
7228 maskedarray version of the numpy function.
7230 """
7231 return np.ndim(getdata(obj))
7233ndim.__doc__ = np.ndim.__doc__
7236def shape(obj):
7237 "maskedarray version of the numpy function."
7238 return np.shape(getdata(obj))
7239shape.__doc__ = np.shape.__doc__
7242def size(obj, axis=None):
7243 "maskedarray version of the numpy function."
7244 return np.size(getdata(obj), axis)
7245size.__doc__ = np.size.__doc__
7248##############################################################################
7249# Extra functions #
7250##############################################################################
7253def where(condition, x=_NoValue, y=_NoValue):
7254 """
7255 Return a masked array with elements from `x` or `y`, depending on condition.
7257 .. note::
7258 When only `condition` is provided, this function is identical to
7259 `nonzero`. The rest of this documentation covers only the case where
7260 all three arguments are provided.
7262 Parameters
7263 ----------
7264 condition : array_like, bool
7265 Where True, yield `x`, otherwise yield `y`.
7266 x, y : array_like, optional
7267 Values from which to choose. `x`, `y` and `condition` need to be
7268 broadcastable to some shape.
7270 Returns
7271 -------
7272 out : MaskedArray
7273 An masked array with `masked` elements where the condition is masked,
7274 elements from `x` where `condition` is True, and elements from `y`
7275 elsewhere.
7277 See Also
7278 --------
7279 numpy.where : Equivalent function in the top-level NumPy module.
7280 nonzero : The function that is called when x and y are omitted
7282 Examples
7283 --------
7284 >>> x = np.ma.array(np.arange(9.).reshape(3, 3), mask=[[0, 1, 0],
7285 ... [1, 0, 1],
7286 ... [0, 1, 0]])
7287 >>> x
7288 masked_array(
7289 data=[[0.0, --, 2.0],
7290 [--, 4.0, --],
7291 [6.0, --, 8.0]],
7292 mask=[[False, True, False],
7293 [ True, False, True],
7294 [False, True, False]],
7295 fill_value=1e+20)
7296 >>> np.ma.where(x > 5, x, -3.1416)
7297 masked_array(
7298 data=[[-3.1416, --, -3.1416],
7299 [--, -3.1416, --],
7300 [6.0, --, 8.0]],
7301 mask=[[False, True, False],
7302 [ True, False, True],
7303 [False, True, False]],
7304 fill_value=1e+20)
7306 """
7308 # handle the single-argument case
7309 missing = (x is _NoValue, y is _NoValue).count(True)
7310 if missing == 1:
7311 raise ValueError("Must provide both 'x' and 'y' or neither.")
7312 if missing == 2:
7313 return nonzero(condition)
7315 # we only care if the condition is true - false or masked pick y
7316 cf = filled(condition, False)
7317 xd = getdata(x)
7318 yd = getdata(y)
7320 # we need the full arrays here for correct final dimensions
7321 cm = getmaskarray(condition)
7322 xm = getmaskarray(x)
7323 ym = getmaskarray(y)
7325 # deal with the fact that masked.dtype == float64, but we don't actually
7326 # want to treat it as that.
7327 if x is masked and y is not masked:
7328 xd = np.zeros((), dtype=yd.dtype)
7329 xm = np.ones((), dtype=ym.dtype)
7330 elif y is masked and x is not masked:
7331 yd = np.zeros((), dtype=xd.dtype)
7332 ym = np.ones((), dtype=xm.dtype)
7334 data = np.where(cf, xd, yd)
7335 mask = np.where(cf, xm, ym)
7336 mask = np.where(cm, np.ones((), dtype=mask.dtype), mask)
7338 # collapse the mask, for backwards compatibility
7339 mask = _shrink_mask(mask)
7341 return masked_array(data, mask=mask)
7344def choose(indices, choices, out=None, mode='raise'):
7345 """
7346 Use an index array to construct a new array from a set of choices.
7348 Given an array of integers and a set of n choice arrays, this method
7349 will create a new array that merges each of the choice arrays. Where a
7350 value in `a` is i, the new array will have the value that choices[i]
7351 contains in the same place.
7353 Parameters
7354 ----------
7355 a : ndarray of ints
7356 This array must contain integers in ``[0, n-1]``, where n is the
7357 number of choices.
7358 choices : sequence of arrays
7359 Choice arrays. The index array and all of the choices should be
7360 broadcastable to the same shape.
7361 out : array, optional
7362 If provided, the result will be inserted into this array. It should
7363 be of the appropriate shape and `dtype`.
7364 mode : {'raise', 'wrap', 'clip'}, optional
7365 Specifies how out-of-bounds indices will behave.
7367 * 'raise' : raise an error
7368 * 'wrap' : wrap around
7369 * 'clip' : clip to the range
7371 Returns
7372 -------
7373 merged_array : array
7375 See Also
7376 --------
7377 choose : equivalent function
7379 Examples
7380 --------
7381 >>> choice = np.array([[1,1,1], [2,2,2], [3,3,3]])
7382 >>> a = np.array([2, 1, 0])
7383 >>> np.ma.choose(a, choice)
7384 masked_array(data=[3, 2, 1],
7385 mask=False,
7386 fill_value=999999)
7388 """
7389 def fmask(x):
7390 "Returns the filled array, or True if masked."
7391 if x is masked:
7392 return True
7393 return filled(x)
7395 def nmask(x):
7396 "Returns the mask, True if ``masked``, False if ``nomask``."
7397 if x is masked:
7398 return True
7399 return getmask(x)
7400 # Get the indices.
7401 c = filled(indices, 0)
7402 # Get the masks.
7403 masks = [nmask(x) for x in choices]
7404 data = [fmask(x) for x in choices]
7405 # Construct the mask
7406 outputmask = np.choose(c, masks, mode=mode)
7407 outputmask = make_mask(mask_or(outputmask, getmask(indices)),
7408 copy=False, shrink=True)
7409 # Get the choices.
7410 d = np.choose(c, data, mode=mode, out=out).view(MaskedArray)
7411 if out is not None:
7412 if isinstance(out, MaskedArray):
7413 out.__setmask__(outputmask)
7414 return out
7415 d.__setmask__(outputmask)
7416 return d
7419def round_(a, decimals=0, out=None):
7420 """
7421 Return a copy of a, rounded to 'decimals' places.
7423 When 'decimals' is negative, it specifies the number of positions
7424 to the left of the decimal point. The real and imaginary parts of
7425 complex numbers are rounded separately. Nothing is done if the
7426 array is not of float type and 'decimals' is greater than or equal
7427 to 0.
7429 Parameters
7430 ----------
7431 decimals : int
7432 Number of decimals to round to. May be negative.
7433 out : array_like
7434 Existing array to use for output.
7435 If not given, returns a default copy of a.
7437 Notes
7438 -----
7439 If out is given and does not have a mask attribute, the mask of a
7440 is lost!
7442 """
7443 if out is None:
7444 return np.round_(a, decimals, out)
7445 else:
7446 np.round_(getdata(a), decimals, out)
7447 if hasattr(out, '_mask'):
7448 out._mask = getmask(a)
7449 return out
7450round = round_
7453# Needed by dot, so move here from extras.py. It will still be exported
7454# from extras.py for compatibility.
7455def mask_rowcols(a, axis=None):
7456 """
7457 Mask rows and/or columns of a 2D array that contain masked values.
7459 Mask whole rows and/or columns of a 2D array that contain
7460 masked values. The masking behavior is selected using the
7461 `axis` parameter.
7463 - If `axis` is None, rows *and* columns are masked.
7464 - If `axis` is 0, only rows are masked.
7465 - If `axis` is 1 or -1, only columns are masked.
7467 Parameters
7468 ----------
7469 a : array_like, MaskedArray
7470 The array to mask. If not a MaskedArray instance (or if no array
7471 elements are masked). The result is a MaskedArray with `mask` set
7472 to `nomask` (False). Must be a 2D array.
7473 axis : int, optional
7474 Axis along which to perform the operation. If None, applies to a
7475 flattened version of the array.
7477 Returns
7478 -------
7479 a : MaskedArray
7480 A modified version of the input array, masked depending on the value
7481 of the `axis` parameter.
7483 Raises
7484 ------
7485 NotImplementedError
7486 If input array `a` is not 2D.
7488 See Also
7489 --------
7490 mask_rows : Mask rows of a 2D array that contain masked values.
7491 mask_cols : Mask cols of a 2D array that contain masked values.
7492 masked_where : Mask where a condition is met.
7494 Notes
7495 -----
7496 The input array's mask is modified by this function.
7498 Examples
7499 --------
7500 >>> import numpy.ma as ma
7501 >>> a = np.zeros((3, 3), dtype=int)
7502 >>> a[1, 1] = 1
7503 >>> a
7504 array([[0, 0, 0],
7505 [0, 1, 0],
7506 [0, 0, 0]])
7507 >>> a = ma.masked_equal(a, 1)
7508 >>> a
7509 masked_array(
7510 data=[[0, 0, 0],
7511 [0, --, 0],
7512 [0, 0, 0]],
7513 mask=[[False, False, False],
7514 [False, True, False],
7515 [False, False, False]],
7516 fill_value=1)
7517 >>> ma.mask_rowcols(a)
7518 masked_array(
7519 data=[[0, --, 0],
7520 [--, --, --],
7521 [0, --, 0]],
7522 mask=[[False, True, False],
7523 [ True, True, True],
7524 [False, True, False]],
7525 fill_value=1)
7527 """
7528 a = array(a, subok=False)
7529 if a.ndim != 2:
7530 raise NotImplementedError("mask_rowcols works for 2D arrays only.")
7531 m = getmask(a)
7532 # Nothing is masked: return a
7533 if m is nomask or not m.any():
7534 return a
7535 maskedval = m.nonzero()
7536 a._mask = a._mask.copy()
7537 if not axis:
7538 a[np.unique(maskedval[0])] = masked
7539 if axis in [None, 1, -1]:
7540 a[:, np.unique(maskedval[1])] = masked
7541 return a
7544# Include masked dot here to avoid import problems in getting it from
7545# extras.py. Note that it is not included in __all__, but rather exported
7546# from extras in order to avoid backward compatibility problems.
7547def dot(a, b, strict=False, out=None):
7548 """
7549 Return the dot product of two arrays.
7551 This function is the equivalent of `numpy.dot` that takes masked values
7552 into account. Note that `strict` and `out` are in different position
7553 than in the method version. In order to maintain compatibility with the
7554 corresponding method, it is recommended that the optional arguments be
7555 treated as keyword only. At some point that may be mandatory.
7557 .. note::
7558 Works only with 2-D arrays at the moment.
7561 Parameters
7562 ----------
7563 a, b : masked_array_like
7564 Inputs arrays.
7565 strict : bool, optional
7566 Whether masked data are propagated (True) or set to 0 (False) for
7567 the computation. Default is False. Propagating the mask means that
7568 if a masked value appears in a row or column, the whole row or
7569 column is considered masked.
7570 out : masked_array, optional
7571 Output argument. This must have the exact kind that would be returned
7572 if it was not used. In particular, it must have the right type, must be
7573 C-contiguous, and its dtype must be the dtype that would be returned
7574 for `dot(a,b)`. This is a performance feature. Therefore, if these
7575 conditions are not met, an exception is raised, instead of attempting
7576 to be flexible.
7578 .. versionadded:: 1.10.2
7580 See Also
7581 --------
7582 numpy.dot : Equivalent function for ndarrays.
7584 Examples
7585 --------
7586 >>> a = np.ma.array([[1, 2, 3], [4, 5, 6]], mask=[[1, 0, 0], [0, 0, 0]])
7587 >>> b = np.ma.array([[1, 2], [3, 4], [5, 6]], mask=[[1, 0], [0, 0], [0, 0]])
7588 >>> np.ma.dot(a, b)
7589 masked_array(
7590 data=[[21, 26],
7591 [45, 64]],
7592 mask=[[False, False],
7593 [False, False]],
7594 fill_value=999999)
7595 >>> np.ma.dot(a, b, strict=True)
7596 masked_array(
7597 data=[[--, --],
7598 [--, 64]],
7599 mask=[[ True, True],
7600 [ True, False]],
7601 fill_value=999999)
7603 """
7604 # !!!: Works only with 2D arrays. There should be a way to get it to run
7605 # with higher dimension
7606 if strict and (a.ndim == 2) and (b.ndim == 2):
7607 a = mask_rowcols(a, 0)
7608 b = mask_rowcols(b, 1)
7609 am = ~getmaskarray(a)
7610 bm = ~getmaskarray(b)
7612 if out is None:
7613 d = np.dot(filled(a, 0), filled(b, 0))
7614 m = ~np.dot(am, bm)
7615 if d.ndim == 0:
7616 d = np.asarray(d)
7617 r = d.view(get_masked_subclass(a, b))
7618 r.__setmask__(m)
7619 return r
7620 else:
7621 d = np.dot(filled(a, 0), filled(b, 0), out._data)
7622 if out.mask.shape != d.shape:
7623 out._mask = np.empty(d.shape, MaskType)
7624 np.dot(am, bm, out._mask)
7625 np.logical_not(out._mask, out._mask)
7626 return out
7629def inner(a, b):
7630 """
7631 Returns the inner product of a and b for arrays of floating point types.
7633 Like the generic NumPy equivalent the product sum is over the last dimension
7634 of a and b. The first argument is not conjugated.
7636 """
7637 fa = filled(a, 0)
7638 fb = filled(b, 0)
7639 if fa.ndim == 0:
7640 fa.shape = (1,)
7641 if fb.ndim == 0:
7642 fb.shape = (1,)
7643 return np.inner(fa, fb).view(MaskedArray)
7644inner.__doc__ = doc_note(np.inner.__doc__,
7645 "Masked values are replaced by 0.")
7646innerproduct = inner
7649def outer(a, b):
7650 "maskedarray version of the numpy function."
7651 fa = filled(a, 0).ravel()
7652 fb = filled(b, 0).ravel()
7653 d = np.outer(fa, fb)
7654 ma = getmask(a)
7655 mb = getmask(b)
7656 if ma is nomask and mb is nomask:
7657 return masked_array(d)
7658 ma = getmaskarray(a)
7659 mb = getmaskarray(b)
7660 m = make_mask(1 - np.outer(1 - ma, 1 - mb), copy=False)
7661 return masked_array(d, mask=m)
7662outer.__doc__ = doc_note(np.outer.__doc__,
7663 "Masked values are replaced by 0.")
7664outerproduct = outer
7667def _convolve_or_correlate(f, a, v, mode, propagate_mask):
7668 """
7669 Helper function for ma.correlate and ma.convolve
7670 """
7671 if propagate_mask:
7672 # results which are contributed to by either item in any pair being invalid
7673 mask = (
7674 f(getmaskarray(a), np.ones(np.shape(v), dtype=bool), mode=mode)
7675 | f(np.ones(np.shape(a), dtype=bool), getmaskarray(v), mode=mode)
7676 )
7677 data = f(getdata(a), getdata(v), mode=mode)
7678 else:
7679 # results which are not contributed to by any pair of valid elements
7680 mask = ~f(~getmaskarray(a), ~getmaskarray(v))
7681 data = f(filled(a, 0), filled(v, 0), mode=mode)
7683 return masked_array(data, mask=mask)
7686def correlate(a, v, mode='valid', propagate_mask=True):
7687 """
7688 Cross-correlation of two 1-dimensional sequences.
7690 Parameters
7691 ----------
7692 a, v : array_like
7693 Input sequences.
7694 mode : {'valid', 'same', 'full'}, optional
7695 Refer to the `np.convolve` docstring. Note that the default
7696 is 'valid', unlike `convolve`, which uses 'full'.
7697 propagate_mask : bool
7698 If True, then a result element is masked if any masked element contributes towards it.
7699 If False, then a result element is only masked if no non-masked element
7700 contribute towards it
7702 Returns
7703 -------
7704 out : MaskedArray
7705 Discrete cross-correlation of `a` and `v`.
7707 See Also
7708 --------
7709 numpy.correlate : Equivalent function in the top-level NumPy module.
7710 """
7711 return _convolve_or_correlate(np.correlate, a, v, mode, propagate_mask)
7714def convolve(a, v, mode='full', propagate_mask=True):
7715 """
7716 Returns the discrete, linear convolution of two one-dimensional sequences.
7718 Parameters
7719 ----------
7720 a, v : array_like
7721 Input sequences.
7722 mode : {'valid', 'same', 'full'}, optional
7723 Refer to the `np.convolve` docstring.
7724 propagate_mask : bool
7725 If True, then if any masked element is included in the sum for a result
7726 element, then the result is masked.
7727 If False, then the result element is only masked if no non-masked cells
7728 contribute towards it
7730 Returns
7731 -------
7732 out : MaskedArray
7733 Discrete, linear convolution of `a` and `v`.
7735 See Also
7736 --------
7737 numpy.convolve : Equivalent function in the top-level NumPy module.
7738 """
7739 return _convolve_or_correlate(np.convolve, a, v, mode, propagate_mask)
7742def allequal(a, b, fill_value=True):
7743 """
7744 Return True if all entries of a and b are equal, using
7745 fill_value as a truth value where either or both are masked.
7747 Parameters
7748 ----------
7749 a, b : array_like
7750 Input arrays to compare.
7751 fill_value : bool, optional
7752 Whether masked values in a or b are considered equal (True) or not
7753 (False).
7755 Returns
7756 -------
7757 y : bool
7758 Returns True if the two arrays are equal within the given
7759 tolerance, False otherwise. If either array contains NaN,
7760 then False is returned.
7762 See Also
7763 --------
7764 all, any
7765 numpy.ma.allclose
7767 Examples
7768 --------
7769 >>> a = np.ma.array([1e10, 1e-7, 42.0], mask=[0, 0, 1])
7770 >>> a
7771 masked_array(data=[10000000000.0, 1e-07, --],
7772 mask=[False, False, True],
7773 fill_value=1e+20)
7775 >>> b = np.array([1e10, 1e-7, -42.0])
7776 >>> b
7777 array([ 1.00000000e+10, 1.00000000e-07, -4.20000000e+01])
7778 >>> np.ma.allequal(a, b, fill_value=False)
7779 False
7780 >>> np.ma.allequal(a, b)
7781 True
7783 """
7784 m = mask_or(getmask(a), getmask(b))
7785 if m is nomask:
7786 x = getdata(a)
7787 y = getdata(b)
7788 d = umath.equal(x, y)
7789 return d.all()
7790 elif fill_value:
7791 x = getdata(a)
7792 y = getdata(b)
7793 d = umath.equal(x, y)
7794 dm = array(d, mask=m, copy=False)
7795 return dm.filled(True).all(None)
7796 else:
7797 return False
7800def allclose(a, b, masked_equal=True, rtol=1e-5, atol=1e-8):
7801 """
7802 Returns True if two arrays are element-wise equal within a tolerance.
7804 This function is equivalent to `allclose` except that masked values
7805 are treated as equal (default) or unequal, depending on the `masked_equal`
7806 argument.
7808 Parameters
7809 ----------
7810 a, b : array_like
7811 Input arrays to compare.
7812 masked_equal : bool, optional
7813 Whether masked values in `a` and `b` are considered equal (True) or not
7814 (False). They are considered equal by default.
7815 rtol : float, optional
7816 Relative tolerance. The relative difference is equal to ``rtol * b``.
7817 Default is 1e-5.
7818 atol : float, optional
7819 Absolute tolerance. The absolute difference is equal to `atol`.
7820 Default is 1e-8.
7822 Returns
7823 -------
7824 y : bool
7825 Returns True if the two arrays are equal within the given
7826 tolerance, False otherwise. If either array contains NaN, then
7827 False is returned.
7829 See Also
7830 --------
7831 all, any
7832 numpy.allclose : the non-masked `allclose`.
7834 Notes
7835 -----
7836 If the following equation is element-wise True, then `allclose` returns
7837 True::
7839 absolute(`a` - `b`) <= (`atol` + `rtol` * absolute(`b`))
7841 Return True if all elements of `a` and `b` are equal subject to
7842 given tolerances.
7844 Examples
7845 --------
7846 >>> a = np.ma.array([1e10, 1e-7, 42.0], mask=[0, 0, 1])
7847 >>> a
7848 masked_array(data=[10000000000.0, 1e-07, --],
7849 mask=[False, False, True],
7850 fill_value=1e+20)
7851 >>> b = np.ma.array([1e10, 1e-8, -42.0], mask=[0, 0, 1])
7852 >>> np.ma.allclose(a, b)
7853 False
7855 >>> a = np.ma.array([1e10, 1e-8, 42.0], mask=[0, 0, 1])
7856 >>> b = np.ma.array([1.00001e10, 1e-9, -42.0], mask=[0, 0, 1])
7857 >>> np.ma.allclose(a, b)
7858 True
7859 >>> np.ma.allclose(a, b, masked_equal=False)
7860 False
7862 Masked values are not compared directly.
7864 >>> a = np.ma.array([1e10, 1e-8, 42.0], mask=[0, 0, 1])
7865 >>> b = np.ma.array([1.00001e10, 1e-9, 42.0], mask=[0, 0, 1])
7866 >>> np.ma.allclose(a, b)
7867 True
7868 >>> np.ma.allclose(a, b, masked_equal=False)
7869 False
7871 """
7872 x = masked_array(a, copy=False)
7873 y = masked_array(b, copy=False)
7875 # make sure y is an inexact type to avoid abs(MIN_INT); will cause
7876 # casting of x later.
7877 dtype = np.result_type(y, 1.)
7878 if y.dtype != dtype:
7879 y = masked_array(y, dtype=dtype, copy=False)
7881 m = mask_or(getmask(x), getmask(y))
7882 xinf = np.isinf(masked_array(x, copy=False, mask=m)).filled(False)
7883 # If we have some infs, they should fall at the same place.
7884 if not np.all(xinf == filled(np.isinf(y), False)):
7885 return False
7886 # No infs at all
7887 if not np.any(xinf):
7888 d = filled(less_equal(absolute(x - y), atol + rtol * absolute(y)),
7889 masked_equal)
7890 return np.all(d)
7892 if not np.all(filled(x[xinf] == y[xinf], masked_equal)):
7893 return False
7894 x = x[~xinf]
7895 y = y[~xinf]
7897 d = filled(less_equal(absolute(x - y), atol + rtol * absolute(y)),
7898 masked_equal)
7900 return np.all(d)
7903def asarray(a, dtype=None, order=None):
7904 """
7905 Convert the input to a masked array of the given data-type.
7907 No copy is performed if the input is already an `ndarray`. If `a` is
7908 a subclass of `MaskedArray`, a base class `MaskedArray` is returned.
7910 Parameters
7911 ----------
7912 a : array_like
7913 Input data, in any form that can be converted to a masked array. This
7914 includes lists, lists of tuples, tuples, tuples of tuples, tuples
7915 of lists, ndarrays and masked arrays.
7916 dtype : dtype, optional
7917 By default, the data-type is inferred from the input data.
7918 order : {'C', 'F'}, optional
7919 Whether to use row-major ('C') or column-major ('FORTRAN') memory
7920 representation. Default is 'C'.
7922 Returns
7923 -------
7924 out : MaskedArray
7925 Masked array interpretation of `a`.
7927 See Also
7928 --------
7929 asanyarray : Similar to `asarray`, but conserves subclasses.
7931 Examples
7932 --------
7933 >>> x = np.arange(10.).reshape(2, 5)
7934 >>> x
7935 array([[0., 1., 2., 3., 4.],
7936 [5., 6., 7., 8., 9.]])
7937 >>> np.ma.asarray(x)
7938 masked_array(
7939 data=[[0., 1., 2., 3., 4.],
7940 [5., 6., 7., 8., 9.]],
7941 mask=False,
7942 fill_value=1e+20)
7943 >>> type(np.ma.asarray(x))
7944 <class 'numpy.ma.core.MaskedArray'>
7946 """
7947 order = order or 'C'
7948 return masked_array(a, dtype=dtype, copy=False, keep_mask=True,
7949 subok=False, order=order)
7952def asanyarray(a, dtype=None):
7953 """
7954 Convert the input to a masked array, conserving subclasses.
7956 If `a` is a subclass of `MaskedArray`, its class is conserved.
7957 No copy is performed if the input is already an `ndarray`.
7959 Parameters
7960 ----------
7961 a : array_like
7962 Input data, in any form that can be converted to an array.
7963 dtype : dtype, optional
7964 By default, the data-type is inferred from the input data.
7965 order : {'C', 'F'}, optional
7966 Whether to use row-major ('C') or column-major ('FORTRAN') memory
7967 representation. Default is 'C'.
7969 Returns
7970 -------
7971 out : MaskedArray
7972 MaskedArray interpretation of `a`.
7974 See Also
7975 --------
7976 asarray : Similar to `asanyarray`, but does not conserve subclass.
7978 Examples
7979 --------
7980 >>> x = np.arange(10.).reshape(2, 5)
7981 >>> x
7982 array([[0., 1., 2., 3., 4.],
7983 [5., 6., 7., 8., 9.]])
7984 >>> np.ma.asanyarray(x)
7985 masked_array(
7986 data=[[0., 1., 2., 3., 4.],
7987 [5., 6., 7., 8., 9.]],
7988 mask=False,
7989 fill_value=1e+20)
7990 >>> type(np.ma.asanyarray(x))
7991 <class 'numpy.ma.core.MaskedArray'>
7993 """
7994 # workaround for #8666, to preserve identity. Ideally the bottom line
7995 # would handle this for us.
7996 if isinstance(a, MaskedArray) and (dtype is None or dtype == a.dtype):
7997 return a
7998 return masked_array(a, dtype=dtype, copy=False, keep_mask=True, subok=True)
8001##############################################################################
8002# Pickling #
8003##############################################################################
8005def _pickle_warn(method):
8006 # NumPy 1.15.0, 2017-12-10
8007 warnings.warn(
8008 f"np.ma.{method} is deprecated, use pickle.{method} instead",
8009 DeprecationWarning, stacklevel=3)
8012def fromfile(file, dtype=float, count=-1, sep=''):
8013 raise NotImplementedError(
8014 "fromfile() not yet implemented for a MaskedArray.")
8017def fromflex(fxarray):
8018 """
8019 Build a masked array from a suitable flexible-type array.
8021 The input array has to have a data-type with ``_data`` and ``_mask``
8022 fields. This type of array is output by `MaskedArray.toflex`.
8024 Parameters
8025 ----------
8026 fxarray : ndarray
8027 The structured input array, containing ``_data`` and ``_mask``
8028 fields. If present, other fields are discarded.
8030 Returns
8031 -------
8032 result : MaskedArray
8033 The constructed masked array.
8035 See Also
8036 --------
8037 MaskedArray.toflex : Build a flexible-type array from a masked array.
8039 Examples
8040 --------
8041 >>> x = np.ma.array(np.arange(9).reshape(3, 3), mask=[0] + [1, 0] * 4)
8042 >>> rec = x.toflex()
8043 >>> rec
8044 array([[(0, False), (1, True), (2, False)],
8045 [(3, True), (4, False), (5, True)],
8046 [(6, False), (7, True), (8, False)]],
8047 dtype=[('_data', '<i8'), ('_mask', '?')])
8048 >>> x2 = np.ma.fromflex(rec)
8049 >>> x2
8050 masked_array(
8051 data=[[0, --, 2],
8052 [--, 4, --],
8053 [6, --, 8]],
8054 mask=[[False, True, False],
8055 [ True, False, True],
8056 [False, True, False]],
8057 fill_value=999999)
8059 Extra fields can be present in the structured array but are discarded:
8061 >>> dt = [('_data', '<i4'), ('_mask', '|b1'), ('field3', '<f4')]
8062 >>> rec2 = np.zeros((2, 2), dtype=dt)
8063 >>> rec2
8064 array([[(0, False, 0.), (0, False, 0.)],
8065 [(0, False, 0.), (0, False, 0.)]],
8066 dtype=[('_data', '<i4'), ('_mask', '?'), ('field3', '<f4')])
8067 >>> y = np.ma.fromflex(rec2)
8068 >>> y
8069 masked_array(
8070 data=[[0, 0],
8071 [0, 0]],
8072 mask=[[False, False],
8073 [False, False]],
8074 fill_value=999999,
8075 dtype=int32)
8077 """
8078 return masked_array(fxarray['_data'], mask=fxarray['_mask'])
8081class _convert2ma:
8083 """
8084 Convert functions from numpy to numpy.ma.
8086 Parameters
8087 ----------
8088 _methodname : string
8089 Name of the method to transform.
8091 """
8092 __doc__ = None
8094 def __init__(self, funcname, params=None):
8095 self._func = getattr(np, funcname)
8096 self.__doc__ = self.getdoc()
8097 self._extras = params or {}
8099 def getdoc(self):
8100 "Return the doc of the function (from the doc of the method)."
8101 doc = getattr(self._func, '__doc__', None)
8102 sig = get_object_signature(self._func)
8103 if doc:
8104 # Add the signature of the function at the beginning of the doc
8105 if sig:
8106 sig = "%s%s\n" % (self._func.__name__, sig)
8107 doc = sig + doc
8108 return doc
8110 def __call__(self, *args, **params):
8111 # Find the common parameters to the call and the definition
8112 _extras = self._extras
8113 common_params = set(params).intersection(_extras)
8114 # Drop the common parameters from the call
8115 for p in common_params:
8116 _extras[p] = params.pop(p)
8117 # Get the result
8118 result = self._func.__call__(*args, **params).view(MaskedArray)
8119 if "fill_value" in common_params:
8120 result.fill_value = _extras.get("fill_value", None)
8121 if "hardmask" in common_params:
8122 result._hardmask = bool(_extras.get("hard_mask", False))
8123 return result
8125arange = _convert2ma('arange', params=dict(fill_value=None, hardmask=False))
8126clip = np.clip
8127diff = np.diff
8128empty = _convert2ma('empty', params=dict(fill_value=None, hardmask=False))
8129empty_like = _convert2ma('empty_like')
8130frombuffer = _convert2ma('frombuffer')
8131fromfunction = _convert2ma('fromfunction')
8132identity = _convert2ma(
8133 'identity', params=dict(fill_value=None, hardmask=False))
8134indices = np.indices
8135ones = _convert2ma('ones', params=dict(fill_value=None, hardmask=False))
8136ones_like = np.ones_like
8137squeeze = np.squeeze
8138zeros = _convert2ma('zeros', params=dict(fill_value=None, hardmask=False))
8139zeros_like = np.zeros_like
8142def append(a, b, axis=None):
8143 """Append values to the end of an array.
8145 .. versionadded:: 1.9.0
8147 Parameters
8148 ----------
8149 a : array_like
8150 Values are appended to a copy of this array.
8151 b : array_like
8152 These values are appended to a copy of `a`. It must be of the
8153 correct shape (the same shape as `a`, excluding `axis`). If `axis`
8154 is not specified, `b` can be any shape and will be flattened
8155 before use.
8156 axis : int, optional
8157 The axis along which `v` are appended. If `axis` is not given,
8158 both `a` and `b` are flattened before use.
8160 Returns
8161 -------
8162 append : MaskedArray
8163 A copy of `a` with `b` appended to `axis`. Note that `append`
8164 does not occur in-place: a new array is allocated and filled. If
8165 `axis` is None, the result is a flattened array.
8167 See Also
8168 --------
8169 numpy.append : Equivalent function in the top-level NumPy module.
8171 Examples
8172 --------
8173 >>> import numpy.ma as ma
8174 >>> a = ma.masked_values([1, 2, 3], 2)
8175 >>> b = ma.masked_values([[4, 5, 6], [7, 8, 9]], 7)
8176 >>> ma.append(a, b)
8177 masked_array(data=[1, --, 3, 4, 5, 6, --, 8, 9],
8178 mask=[False, True, False, False, False, False, True, False,
8179 False],
8180 fill_value=999999)
8181 """
8182 return concatenate([a, b], axis)