Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.9/dist-packages/numpy/ma/core.py: 26%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

2460 statements  

1""" 

2numpy.ma : a package to handle missing or invalid values. 

3 

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. 

9 

10 

11Copyright 1999, 2000, 2001 Regents of the University of California. 

12Released for unlimited redistribution. 

13 

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) 

18 

19.. moduleauthor:: Pierre Gerard-Marchant 

20 

21""" 

22# pylint: disable-msg=E1002 

23import builtins 

24import inspect 

25import operator 

26import warnings 

27import textwrap 

28import re 

29from functools import reduce 

30 

31import numpy as np 

32import numpy.core.umath as umath 

33import numpy.core.numerictypes as ntypes 

34from numpy.core import multiarray as mu 

35from numpy import ndarray, amax, amin, iscomplexobj, bool_, _NoValue 

36from numpy import array as narray 

37from numpy.lib.function_base import angle 

38from numpy.compat import ( 

39 getargspec, formatargspec, long, unicode, bytes 

40 ) 

41from numpy import expand_dims 

42from numpy.core.numeric import normalize_axis_tuple 

43 

44 

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', 'ones_like', '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', 'zeros_like', 

79 ] 

80 

81MaskType = np.bool_ 

82nomask = MaskType(0) 

83 

84class MaskedArrayFutureWarning(FutureWarning): 

85 pass 

86 

87def _deprecate_argsort_axis(arr): 

88 """ 

89 Adjust the axis passed to argsort, warning if necessary 

90 

91 Parameters 

92 ---------- 

93 arr 

94 The array which argsort was called on 

95 

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 

113 

114 

115def doc_note(initialdoc, note): 

116 """ 

117 Adds a Notes section to an existing docstring. 

118 

119 """ 

120 if initialdoc is None: 

121 return 

122 if note is None: 

123 return initialdoc 

124 

125 notesplit = re.split(r'\n\s*?Notes\n\s*?-----', inspect.cleandoc(initialdoc)) 

126 notedoc = "\n\nNotes\n-----\n%s\n" % inspect.cleandoc(note) 

127 

128 return ''.join(notesplit[:1] + [notedoc] + notesplit[1:]) 

129 

130 

131def get_object_signature(obj): 

132 """ 

133 Get the signature from obj 

134 

135 """ 

136 try: 

137 sig = formatargspec(*getargspec(obj)) 

138 except TypeError: 

139 sig = '' 

140 return sig 

141 

142 

143############################################################################### 

144# Exceptions # 

145############################################################################### 

146 

147 

148class MAError(Exception): 

149 """ 

150 Class for masked array related errors. 

151 

152 """ 

153 pass 

154 

155 

156class MaskError(MAError): 

157 """ 

158 Class for mask related errors. 

159 

160 """ 

161 pass 

162 

163 

164############################################################################### 

165# Filling options # 

166############################################################################### 

167 

168 

169# b: boolean - c: complex - f: floats - i: integer - O: object - S: string 

170default_filler = {'b': True, 

171 'c': 1.e20 + 0.0j, 

172 'f': 1.e20, 

173 'i': 999999, 

174 'O': '?', 

175 'S': b'N/A', 

176 'u': 999999, 

177 'V': b'???', 

178 'U': 'N/A' 

179 } 

180 

181# Add datetime64 and timedelta64 types 

182for v in ["Y", "M", "W", "D", "h", "m", "s", "ms", "us", "ns", "ps", 

183 "fs", "as"]: 

184 default_filler["M8[" + v + "]"] = np.datetime64("NaT", v) 

185 default_filler["m8[" + v + "]"] = np.timedelta64("NaT", v) 

186 

187float_types_list = [np.half, np.single, np.double, np.longdouble, 

188 np.csingle, np.cdouble, np.clongdouble] 

189max_filler = ntypes._minvals 

190max_filler.update([(k, -np.inf) for k in float_types_list[:4]]) 

191max_filler.update([(k, complex(-np.inf, -np.inf)) for k in float_types_list[-3:]]) 

192 

193min_filler = ntypes._maxvals 

194min_filler.update([(k, +np.inf) for k in float_types_list[:4]]) 

195min_filler.update([(k, complex(+np.inf, +np.inf)) for k in float_types_list[-3:]]) 

196 

197del float_types_list 

198 

199def _recursive_fill_value(dtype, f): 

200 """ 

201 Recursively produce a fill value for `dtype`, calling f on scalar dtypes 

202 """ 

203 if dtype.names is not None: 

204 # We wrap into `array` here, which ensures we use NumPy cast rules 

205 # for integer casts, this allows the use of 99999 as a fill value 

206 # for int8. 

207 # TODO: This is probably a mess, but should best preserve behavior? 

208 vals = tuple( 

209 np.array(_recursive_fill_value(dtype[name], f)) 

210 for name in dtype.names) 

211 return np.array(vals, dtype=dtype)[()] # decay to void scalar from 0d 

212 elif dtype.subdtype: 

213 subtype, shape = dtype.subdtype 

214 subval = _recursive_fill_value(subtype, f) 

215 return np.full(shape, subval) 

216 else: 

217 return f(dtype) 

218 

219 

220def _get_dtype_of(obj): 

221 """ Convert the argument for *_fill_value into a dtype """ 

222 if isinstance(obj, np.dtype): 

223 return obj 

224 elif hasattr(obj, 'dtype'): 

225 return obj.dtype 

226 else: 

227 return np.asanyarray(obj).dtype 

228 

229 

230def default_fill_value(obj): 

231 """ 

232 Return the default fill value for the argument object. 

233 

234 The default filling value depends on the datatype of the input 

235 array or the type of the input scalar: 

236 

237 ======== ======== 

238 datatype default 

239 ======== ======== 

240 bool True 

241 int 999999 

242 float 1.e20 

243 complex 1.e20+0j 

244 object '?' 

245 string 'N/A' 

246 ======== ======== 

247 

248 For structured types, a structured scalar is returned, with each field the 

249 default fill value for its type. 

250 

251 For subarray types, the fill value is an array of the same size containing 

252 the default scalar fill value. 

253 

254 Parameters 

255 ---------- 

256 obj : ndarray, dtype or scalar 

257 The array data-type or scalar for which the default fill value 

258 is returned. 

259 

260 Returns 

261 ------- 

262 fill_value : scalar 

263 The default fill value. 

264 

265 Examples 

266 -------- 

267 >>> np.ma.default_fill_value(1) 

268 999999 

269 >>> np.ma.default_fill_value(np.array([1.1, 2., np.pi])) 

270 1e+20 

271 >>> np.ma.default_fill_value(np.dtype(complex)) 

272 (1e+20+0j) 

273 

274 """ 

275 def _scalar_fill_value(dtype): 

276 if dtype.kind in 'Mm': 

277 return default_filler.get(dtype.str[1:], '?') 

278 else: 

279 return default_filler.get(dtype.kind, '?') 

280 

281 dtype = _get_dtype_of(obj) 

282 return _recursive_fill_value(dtype, _scalar_fill_value) 

283 

284 

285def _extremum_fill_value(obj, extremum, extremum_name): 

286 

287 def _scalar_fill_value(dtype): 

288 try: 

289 return extremum[dtype] 

290 except KeyError as e: 

291 raise TypeError( 

292 f"Unsuitable type {dtype} for calculating {extremum_name}." 

293 ) from None 

294 

295 dtype = _get_dtype_of(obj) 

296 return _recursive_fill_value(dtype, _scalar_fill_value) 

297 

298 

299def minimum_fill_value(obj): 

300 """ 

301 Return the maximum value that can be represented by the dtype of an object. 

302 

303 This function is useful for calculating a fill value suitable for 

304 taking the minimum of an array with a given dtype. 

305 

306 Parameters 

307 ---------- 

308 obj : ndarray, dtype or scalar 

309 An object that can be queried for it's numeric type. 

310 

311 Returns 

312 ------- 

313 val : scalar 

314 The maximum representable value. 

315 

316 Raises 

317 ------ 

318 TypeError 

319 If `obj` isn't a suitable numeric type. 

320 

321 See Also 

322 -------- 

323 maximum_fill_value : The inverse function. 

324 set_fill_value : Set the filling value of a masked array. 

325 MaskedArray.fill_value : Return current fill value. 

326 

327 Examples 

328 -------- 

329 >>> import numpy.ma as ma 

330 >>> a = np.int8() 

331 >>> ma.minimum_fill_value(a) 

332 127 

333 >>> a = np.int32() 

334 >>> ma.minimum_fill_value(a) 

335 2147483647 

336 

337 An array of numeric data can also be passed. 

338 

339 >>> a = np.array([1, 2, 3], dtype=np.int8) 

340 >>> ma.minimum_fill_value(a) 

341 127 

342 >>> a = np.array([1, 2, 3], dtype=np.float32) 

343 >>> ma.minimum_fill_value(a) 

344 inf 

345 

346 """ 

347 return _extremum_fill_value(obj, min_filler, "minimum") 

348 

349 

350def maximum_fill_value(obj): 

351 """ 

352 Return the minimum value that can be represented by the dtype of an object. 

353 

354 This function is useful for calculating a fill value suitable for 

355 taking the maximum of an array with a given dtype. 

356 

357 Parameters 

358 ---------- 

359 obj : ndarray, dtype or scalar 

360 An object that can be queried for it's numeric type. 

361 

362 Returns 

363 ------- 

364 val : scalar 

365 The minimum representable value. 

366 

367 Raises 

368 ------ 

369 TypeError 

370 If `obj` isn't a suitable numeric type. 

371 

372 See Also 

373 -------- 

374 minimum_fill_value : The inverse function. 

375 set_fill_value : Set the filling value of a masked array. 

376 MaskedArray.fill_value : Return current fill value. 

377 

378 Examples 

379 -------- 

380 >>> import numpy.ma as ma 

381 >>> a = np.int8() 

382 >>> ma.maximum_fill_value(a) 

383 -128 

384 >>> a = np.int32() 

385 >>> ma.maximum_fill_value(a) 

386 -2147483648 

387 

388 An array of numeric data can also be passed. 

389 

390 >>> a = np.array([1, 2, 3], dtype=np.int8) 

391 >>> ma.maximum_fill_value(a) 

392 -128 

393 >>> a = np.array([1, 2, 3], dtype=np.float32) 

394 >>> ma.maximum_fill_value(a) 

395 -inf 

396 

397 """ 

398 return _extremum_fill_value(obj, max_filler, "maximum") 

399 

400 

401def _recursive_set_fill_value(fillvalue, dt): 

402 """ 

403 Create a fill value for a structured dtype. 

404 

405 Parameters 

406 ---------- 

407 fillvalue : scalar or array_like 

408 Scalar or array representing the fill value. If it is of shorter 

409 length than the number of fields in dt, it will be resized. 

410 dt : dtype 

411 The structured dtype for which to create the fill value. 

412 

413 Returns 

414 ------- 

415 val : tuple 

416 A tuple of values corresponding to the structured fill value. 

417 

418 """ 

419 fillvalue = np.resize(fillvalue, len(dt.names)) 

420 output_value = [] 

421 for (fval, name) in zip(fillvalue, dt.names): 

422 cdtype = dt[name] 

423 if cdtype.subdtype: 

424 cdtype = cdtype.subdtype[0] 

425 

426 if cdtype.names is not None: 

427 output_value.append(tuple(_recursive_set_fill_value(fval, cdtype))) 

428 else: 

429 output_value.append(np.array(fval, dtype=cdtype).item()) 

430 return tuple(output_value) 

431 

432 

433def _check_fill_value(fill_value, ndtype): 

434 """ 

435 Private function validating the given `fill_value` for the given dtype. 

436 

437 If fill_value is None, it is set to the default corresponding to the dtype. 

438 

439 If fill_value is not None, its value is forced to the given dtype. 

440 

441 The result is always a 0d array. 

442 

443 """ 

444 ndtype = np.dtype(ndtype) 

445 if fill_value is None: 

446 fill_value = default_fill_value(ndtype) 

447 elif ndtype.names is not None: 

448 if isinstance(fill_value, (ndarray, np.void)): 

449 try: 

450 fill_value = np.array(fill_value, copy=False, dtype=ndtype) 

451 except ValueError as e: 

452 err_msg = "Unable to transform %s to dtype %s" 

453 raise ValueError(err_msg % (fill_value, ndtype)) from e 

454 else: 

455 fill_value = np.asarray(fill_value, dtype=object) 

456 fill_value = np.array(_recursive_set_fill_value(fill_value, ndtype), 

457 dtype=ndtype) 

458 else: 

459 if isinstance(fill_value, str) and (ndtype.char not in 'OSVU'): 

460 # Note this check doesn't work if fill_value is not a scalar 

461 err_msg = "Cannot set fill value of string with array of dtype %s" 

462 raise TypeError(err_msg % ndtype) 

463 else: 

464 # In case we want to convert 1e20 to int. 

465 # Also in case of converting string arrays. 

466 try: 

467 fill_value = np.array(fill_value, copy=False, dtype=ndtype) 

468 except (OverflowError, ValueError) as e: 

469 # Raise TypeError instead of OverflowError or ValueError. 

470 # OverflowError is seldom used, and the real problem here is 

471 # that the passed fill_value is not compatible with the ndtype. 

472 err_msg = "Cannot convert fill_value %s to dtype %s" 

473 raise TypeError(err_msg % (fill_value, ndtype)) from e 

474 return np.array(fill_value) 

475 

476 

477def set_fill_value(a, fill_value): 

478 """ 

479 Set the filling value of a, if a is a masked array. 

480 

481 This function changes the fill value of the masked array `a` in place. 

482 If `a` is not a masked array, the function returns silently, without 

483 doing anything. 

484 

485 Parameters 

486 ---------- 

487 a : array_like 

488 Input array. 

489 fill_value : dtype 

490 Filling value. A consistency test is performed to make sure 

491 the value is compatible with the dtype of `a`. 

492 

493 Returns 

494 ------- 

495 None 

496 Nothing returned by this function. 

497 

498 See Also 

499 -------- 

500 maximum_fill_value : Return the default fill value for a dtype. 

501 MaskedArray.fill_value : Return current fill value. 

502 MaskedArray.set_fill_value : Equivalent method. 

503 

504 Examples 

505 -------- 

506 >>> import numpy.ma as ma 

507 >>> a = np.arange(5) 

508 >>> a 

509 array([0, 1, 2, 3, 4]) 

510 >>> a = ma.masked_where(a < 3, a) 

511 >>> a 

512 masked_array(data=[--, --, --, 3, 4], 

513 mask=[ True, True, True, False, False], 

514 fill_value=999999) 

515 >>> ma.set_fill_value(a, -999) 

516 >>> a 

517 masked_array(data=[--, --, --, 3, 4], 

518 mask=[ True, True, True, False, False], 

519 fill_value=-999) 

520 

521 Nothing happens if `a` is not a masked array. 

522 

523 >>> a = list(range(5)) 

524 >>> a 

525 [0, 1, 2, 3, 4] 

526 >>> ma.set_fill_value(a, 100) 

527 >>> a 

528 [0, 1, 2, 3, 4] 

529 >>> a = np.arange(5) 

530 >>> a 

531 array([0, 1, 2, 3, 4]) 

532 >>> ma.set_fill_value(a, 100) 

533 >>> a 

534 array([0, 1, 2, 3, 4]) 

535 

536 """ 

537 if isinstance(a, MaskedArray): 

538 a.set_fill_value(fill_value) 

539 return 

540 

541 

542def get_fill_value(a): 

543 """ 

544 Return the filling value of a, if any. Otherwise, returns the 

545 default filling value for that type. 

546 

547 """ 

548 if isinstance(a, MaskedArray): 

549 result = a.fill_value 

550 else: 

551 result = default_fill_value(a) 

552 return result 

553 

554 

555def common_fill_value(a, b): 

556 """ 

557 Return the common filling value of two masked arrays, if any. 

558 

559 If ``a.fill_value == b.fill_value``, return the fill value, 

560 otherwise return None. 

561 

562 Parameters 

563 ---------- 

564 a, b : MaskedArray 

565 The masked arrays for which to compare fill values. 

566 

567 Returns 

568 ------- 

569 fill_value : scalar or None 

570 The common fill value, or None. 

571 

572 Examples 

573 -------- 

574 >>> x = np.ma.array([0, 1.], fill_value=3) 

575 >>> y = np.ma.array([0, 1.], fill_value=3) 

576 >>> np.ma.common_fill_value(x, y) 

577 3.0 

578 

579 """ 

580 t1 = get_fill_value(a) 

581 t2 = get_fill_value(b) 

582 if t1 == t2: 

583 return t1 

584 return None 

585 

586 

587def filled(a, fill_value=None): 

588 """ 

589 Return input as an array with masked data replaced by a fill value. 

590 

591 If `a` is not a `MaskedArray`, `a` itself is returned. 

592 If `a` is a `MaskedArray` and `fill_value` is None, `fill_value` is set to 

593 ``a.fill_value``. 

594 

595 Parameters 

596 ---------- 

597 a : MaskedArray or array_like 

598 An input object. 

599 fill_value : array_like, optional. 

600 Can be scalar or non-scalar. If non-scalar, the 

601 resulting filled array should be broadcastable 

602 over input array. Default is None. 

603 

604 Returns 

605 ------- 

606 a : ndarray 

607 The filled array. 

608 

609 See Also 

610 -------- 

611 compressed 

612 

613 Examples 

614 -------- 

615 >>> x = np.ma.array(np.arange(9).reshape(3, 3), mask=[[1, 0, 0], 

616 ... [1, 0, 0], 

617 ... [0, 0, 0]]) 

618 >>> x.filled() 

619 array([[999999, 1, 2], 

620 [999999, 4, 5], 

621 [ 6, 7, 8]]) 

622 >>> x.filled(fill_value=333) 

623 array([[333, 1, 2], 

624 [333, 4, 5], 

625 [ 6, 7, 8]]) 

626 >>> x.filled(fill_value=np.arange(3)) 

627 array([[0, 1, 2], 

628 [0, 4, 5], 

629 [6, 7, 8]]) 

630 

631 """ 

632 if hasattr(a, 'filled'): 

633 return a.filled(fill_value) 

634 

635 elif isinstance(a, ndarray): 

636 # Should we check for contiguity ? and a.flags['CONTIGUOUS']: 

637 return a 

638 elif isinstance(a, dict): 

639 return np.array(a, 'O') 

640 else: 

641 return np.array(a) 

642 

643 

644def get_masked_subclass(*arrays): 

645 """ 

646 Return the youngest subclass of MaskedArray from a list of (masked) arrays. 

647 

648 In case of siblings, the first listed takes over. 

649 

650 """ 

651 if len(arrays) == 1: 

652 arr = arrays[0] 

653 if isinstance(arr, MaskedArray): 

654 rcls = type(arr) 

655 else: 

656 rcls = MaskedArray 

657 else: 

658 arrcls = [type(a) for a in arrays] 

659 rcls = arrcls[0] 

660 if not issubclass(rcls, MaskedArray): 

661 rcls = MaskedArray 

662 for cls in arrcls[1:]: 

663 if issubclass(cls, rcls): 

664 rcls = cls 

665 # Don't return MaskedConstant as result: revert to MaskedArray 

666 if rcls.__name__ == 'MaskedConstant': 

667 return MaskedArray 

668 return rcls 

669 

670 

671def getdata(a, subok=True): 

672 """ 

673 Return the data of a masked array as an ndarray. 

674 

675 Return the data of `a` (if any) as an ndarray if `a` is a ``MaskedArray``, 

676 else return `a` as a ndarray or subclass (depending on `subok`) if not. 

677 

678 Parameters 

679 ---------- 

680 a : array_like 

681 Input ``MaskedArray``, alternatively a ndarray or a subclass thereof. 

682 subok : bool 

683 Whether to force the output to be a `pure` ndarray (False) or to 

684 return a subclass of ndarray if appropriate (True, default). 

685 

686 See Also 

687 -------- 

688 getmask : Return the mask of a masked array, or nomask. 

689 getmaskarray : Return the mask of a masked array, or full array of False. 

690 

691 Examples 

692 -------- 

693 >>> import numpy.ma as ma 

694 >>> a = ma.masked_equal([[1,2],[3,4]], 2) 

695 >>> a 

696 masked_array( 

697 data=[[1, --], 

698 [3, 4]], 

699 mask=[[False, True], 

700 [False, False]], 

701 fill_value=2) 

702 >>> ma.getdata(a) 

703 array([[1, 2], 

704 [3, 4]]) 

705 

706 Equivalently use the ``MaskedArray`` `data` attribute. 

707 

708 >>> a.data 

709 array([[1, 2], 

710 [3, 4]]) 

711 

712 """ 

713 try: 

714 data = a._data 

715 except AttributeError: 

716 data = np.array(a, copy=False, subok=subok) 

717 if not subok: 

718 return data.view(ndarray) 

719 return data 

720 

721 

722get_data = getdata 

723 

724 

725def fix_invalid(a, mask=nomask, copy=True, fill_value=None): 

726 """ 

727 Return input with invalid data masked and replaced by a fill value. 

728 

729 Invalid data means values of `nan`, `inf`, etc. 

730 

731 Parameters 

732 ---------- 

733 a : array_like 

734 Input array, a (subclass of) ndarray. 

735 mask : sequence, optional 

736 Mask. Must be convertible to an array of booleans with the same 

737 shape as `data`. True indicates a masked (i.e. invalid) data. 

738 copy : bool, optional 

739 Whether to use a copy of `a` (True) or to fix `a` in place (False). 

740 Default is True. 

741 fill_value : scalar, optional 

742 Value used for fixing invalid data. Default is None, in which case 

743 the ``a.fill_value`` is used. 

744 

745 Returns 

746 ------- 

747 b : MaskedArray 

748 The input array with invalid entries fixed. 

749 

750 Notes 

751 ----- 

752 A copy is performed by default. 

753 

754 Examples 

755 -------- 

756 >>> x = np.ma.array([1., -1, np.nan, np.inf], mask=[1] + [0]*3) 

757 >>> x 

758 masked_array(data=[--, -1.0, nan, inf], 

759 mask=[ True, False, False, False], 

760 fill_value=1e+20) 

761 >>> np.ma.fix_invalid(x) 

762 masked_array(data=[--, -1.0, --, --], 

763 mask=[ True, False, True, True], 

764 fill_value=1e+20) 

765 

766 >>> fixed = np.ma.fix_invalid(x) 

767 >>> fixed.data 

768 array([ 1.e+00, -1.e+00, 1.e+20, 1.e+20]) 

769 >>> x.data 

770 array([ 1., -1., nan, inf]) 

771 

772 """ 

773 a = masked_array(a, copy=copy, mask=mask, subok=True) 

774 invalid = np.logical_not(np.isfinite(a._data)) 

775 if not invalid.any(): 

776 return a 

777 a._mask |= invalid 

778 if fill_value is None: 

779 fill_value = a.fill_value 

780 a._data[invalid] = fill_value 

781 return a 

782 

783def is_string_or_list_of_strings(val): 

784 return (isinstance(val, str) or 

785 (isinstance(val, list) and val and 

786 builtins.all(isinstance(s, str) for s in val))) 

787 

788############################################################################### 

789# Ufuncs # 

790############################################################################### 

791 

792 

793ufunc_domain = {} 

794ufunc_fills = {} 

795 

796 

797class _DomainCheckInterval: 

798 """ 

799 Define a valid interval, so that : 

800 

801 ``domain_check_interval(a,b)(x) == True`` where 

802 ``x < a`` or ``x > b``. 

803 

804 """ 

805 

806 def __init__(self, a, b): 

807 "domain_check_interval(a,b)(x) = true where x < a or y > b" 

808 if a > b: 

809 (a, b) = (b, a) 

810 self.a = a 

811 self.b = b 

812 

813 def __call__(self, x): 

814 "Execute the call behavior." 

815 # nans at masked positions cause RuntimeWarnings, even though 

816 # they are masked. To avoid this we suppress warnings. 

817 with np.errstate(invalid='ignore'): 

818 return umath.logical_or(umath.greater(x, self.b), 

819 umath.less(x, self.a)) 

820 

821 

822class _DomainTan: 

823 """ 

824 Define a valid interval for the `tan` function, so that: 

825 

826 ``domain_tan(eps) = True`` where ``abs(cos(x)) < eps`` 

827 

828 """ 

829 

830 def __init__(self, eps): 

831 "domain_tan(eps) = true where abs(cos(x)) < eps)" 

832 self.eps = eps 

833 

834 def __call__(self, x): 

835 "Executes the call behavior." 

836 with np.errstate(invalid='ignore'): 

837 return umath.less(umath.absolute(umath.cos(x)), self.eps) 

838 

839 

840class _DomainSafeDivide: 

841 """ 

842 Define a domain for safe division. 

843 

844 """ 

845 

846 def __init__(self, tolerance=None): 

847 self.tolerance = tolerance 

848 

849 def __call__(self, a, b): 

850 # Delay the selection of the tolerance to here in order to reduce numpy 

851 # import times. The calculation of these parameters is a substantial 

852 # component of numpy's import time. 

853 if self.tolerance is None: 

854 self.tolerance = np.finfo(float).tiny 

855 # don't call ma ufuncs from __array_wrap__ which would fail for scalars 

856 a, b = np.asarray(a), np.asarray(b) 

857 with np.errstate(invalid='ignore'): 

858 return umath.absolute(a) * self.tolerance >= umath.absolute(b) 

859 

860 

861class _DomainGreater: 

862 """ 

863 DomainGreater(v)(x) is True where x <= v. 

864 

865 """ 

866 

867 def __init__(self, critical_value): 

868 "DomainGreater(v)(x) = true where x <= v" 

869 self.critical_value = critical_value 

870 

871 def __call__(self, x): 

872 "Executes the call behavior." 

873 with np.errstate(invalid='ignore'): 

874 return umath.less_equal(x, self.critical_value) 

875 

876 

877class _DomainGreaterEqual: 

878 """ 

879 DomainGreaterEqual(v)(x) is True where x < v. 

880 

881 """ 

882 

883 def __init__(self, critical_value): 

884 "DomainGreaterEqual(v)(x) = true where x < v" 

885 self.critical_value = critical_value 

886 

887 def __call__(self, x): 

888 "Executes the call behavior." 

889 with np.errstate(invalid='ignore'): 

890 return umath.less(x, self.critical_value) 

891 

892 

893class _MaskedUFunc: 

894 def __init__(self, ufunc): 

895 self.f = ufunc 

896 self.__doc__ = ufunc.__doc__ 

897 self.__name__ = ufunc.__name__ 

898 

899 def __str__(self): 

900 return f"Masked version of {self.f}" 

901 

902 

903class _MaskedUnaryOperation(_MaskedUFunc): 

904 """ 

905 Defines masked version of unary operations, where invalid values are 

906 pre-masked. 

907 

908 Parameters 

909 ---------- 

910 mufunc : callable 

911 The function for which to define a masked version. Made available 

912 as ``_MaskedUnaryOperation.f``. 

913 fill : scalar, optional 

914 Filling value, default is 0. 

915 domain : class instance 

916 Domain for the function. Should be one of the ``_Domain*`` 

917 classes. Default is None. 

918 

919 """ 

920 

921 def __init__(self, mufunc, fill=0, domain=None): 

922 super().__init__(mufunc) 

923 self.fill = fill 

924 self.domain = domain 

925 ufunc_domain[mufunc] = domain 

926 ufunc_fills[mufunc] = fill 

927 

928 def __call__(self, a, *args, **kwargs): 

929 """ 

930 Execute the call behavior. 

931 

932 """ 

933 d = getdata(a) 

934 # Deal with domain 

935 if self.domain is not None: 

936 # Case 1.1. : Domained function 

937 # nans at masked positions cause RuntimeWarnings, even though 

938 # they are masked. To avoid this we suppress warnings. 

939 with np.errstate(divide='ignore', invalid='ignore'): 

940 result = self.f(d, *args, **kwargs) 

941 # Make a mask 

942 m = ~umath.isfinite(result) 

943 m |= self.domain(d) 

944 m |= getmask(a) 

945 else: 

946 # Case 1.2. : Function without a domain 

947 # Get the result and the mask 

948 with np.errstate(divide='ignore', invalid='ignore'): 

949 result = self.f(d, *args, **kwargs) 

950 m = getmask(a) 

951 

952 if not result.ndim: 

953 # Case 2.1. : The result is scalarscalar 

954 if m: 

955 return masked 

956 return result 

957 

958 if m is not nomask: 

959 # Case 2.2. The result is an array 

960 # We need to fill the invalid data back w/ the input Now, 

961 # that's plain silly: in C, we would just skip the element and 

962 # keep the original, but we do have to do it that way in Python 

963 

964 # In case result has a lower dtype than the inputs (as in 

965 # equal) 

966 try: 

967 np.copyto(result, d, where=m) 

968 except TypeError: 

969 pass 

970 # Transform to 

971 masked_result = result.view(get_masked_subclass(a)) 

972 masked_result._mask = m 

973 masked_result._update_from(a) 

974 return masked_result 

975 

976 

977class _MaskedBinaryOperation(_MaskedUFunc): 

978 """ 

979 Define masked version of binary operations, where invalid 

980 values are pre-masked. 

981 

982 Parameters 

983 ---------- 

984 mbfunc : function 

985 The function for which to define a masked version. Made available 

986 as ``_MaskedBinaryOperation.f``. 

987 domain : class instance 

988 Default domain for the function. Should be one of the ``_Domain*`` 

989 classes. Default is None. 

990 fillx : scalar, optional 

991 Filling value for the first argument, default is 0. 

992 filly : scalar, optional 

993 Filling value for the second argument, default is 0. 

994 

995 """ 

996 

997 def __init__(self, mbfunc, fillx=0, filly=0): 

998 """ 

999 abfunc(fillx, filly) must be defined. 

1000 

1001 abfunc(x, filly) = x for all x to enable reduce. 

1002 

1003 """ 

1004 super().__init__(mbfunc) 

1005 self.fillx = fillx 

1006 self.filly = filly 

1007 ufunc_domain[mbfunc] = None 

1008 ufunc_fills[mbfunc] = (fillx, filly) 

1009 

1010 def __call__(self, a, b, *args, **kwargs): 

1011 """ 

1012 Execute the call behavior. 

1013 

1014 """ 

1015 # Get the data, as ndarray 

1016 (da, db) = (getdata(a), getdata(b)) 

1017 # Get the result 

1018 with np.errstate(): 

1019 np.seterr(divide='ignore', invalid='ignore') 

1020 result = self.f(da, db, *args, **kwargs) 

1021 # Get the mask for the result 

1022 (ma, mb) = (getmask(a), getmask(b)) 

1023 if ma is nomask: 

1024 if mb is nomask: 

1025 m = nomask 

1026 else: 

1027 m = umath.logical_or(getmaskarray(a), mb) 

1028 elif mb is nomask: 

1029 m = umath.logical_or(ma, getmaskarray(b)) 

1030 else: 

1031 m = umath.logical_or(ma, mb) 

1032 

1033 # Case 1. : scalar 

1034 if not result.ndim: 

1035 if m: 

1036 return masked 

1037 return result 

1038 

1039 # Case 2. : array 

1040 # Revert result to da where masked 

1041 if m is not nomask and m.any(): 

1042 # any errors, just abort; impossible to guarantee masked values 

1043 try: 

1044 np.copyto(result, da, casting='unsafe', where=m) 

1045 except Exception: 

1046 pass 

1047 

1048 # Transforms to a (subclass of) MaskedArray 

1049 masked_result = result.view(get_masked_subclass(a, b)) 

1050 masked_result._mask = m 

1051 if isinstance(a, MaskedArray): 

1052 masked_result._update_from(a) 

1053 elif isinstance(b, MaskedArray): 

1054 masked_result._update_from(b) 

1055 return masked_result 

1056 

1057 def reduce(self, target, axis=0, dtype=None): 

1058 """ 

1059 Reduce `target` along the given `axis`. 

1060 

1061 """ 

1062 tclass = get_masked_subclass(target) 

1063 m = getmask(target) 

1064 t = filled(target, self.filly) 

1065 if t.shape == (): 

1066 t = t.reshape(1) 

1067 if m is not nomask: 

1068 m = make_mask(m, copy=True) 

1069 m.shape = (1,) 

1070 

1071 if m is nomask: 

1072 tr = self.f.reduce(t, axis) 

1073 mr = nomask 

1074 else: 

1075 tr = self.f.reduce(t, axis, dtype=dtype) 

1076 mr = umath.logical_and.reduce(m, axis) 

1077 

1078 if not tr.shape: 

1079 if mr: 

1080 return masked 

1081 else: 

1082 return tr 

1083 masked_tr = tr.view(tclass) 

1084 masked_tr._mask = mr 

1085 return masked_tr 

1086 

1087 def outer(self, a, b): 

1088 """ 

1089 Return the function applied to the outer product of a and b. 

1090 

1091 """ 

1092 (da, db) = (getdata(a), getdata(b)) 

1093 d = self.f.outer(da, db) 

1094 ma = getmask(a) 

1095 mb = getmask(b) 

1096 if ma is nomask and mb is nomask: 

1097 m = nomask 

1098 else: 

1099 ma = getmaskarray(a) 

1100 mb = getmaskarray(b) 

1101 m = umath.logical_or.outer(ma, mb) 

1102 if (not m.ndim) and m: 

1103 return masked 

1104 if m is not nomask: 

1105 np.copyto(d, da, where=m) 

1106 if not d.shape: 

1107 return d 

1108 masked_d = d.view(get_masked_subclass(a, b)) 

1109 masked_d._mask = m 

1110 return masked_d 

1111 

1112 def accumulate(self, target, axis=0): 

1113 """Accumulate `target` along `axis` after filling with y fill 

1114 value. 

1115 

1116 """ 

1117 tclass = get_masked_subclass(target) 

1118 t = filled(target, self.filly) 

1119 result = self.f.accumulate(t, axis) 

1120 masked_result = result.view(tclass) 

1121 return masked_result 

1122 

1123 

1124 

1125class _DomainedBinaryOperation(_MaskedUFunc): 

1126 """ 

1127 Define binary operations that have a domain, like divide. 

1128 

1129 They have no reduce, outer or accumulate. 

1130 

1131 Parameters 

1132 ---------- 

1133 mbfunc : function 

1134 The function for which to define a masked version. Made available 

1135 as ``_DomainedBinaryOperation.f``. 

1136 domain : class instance 

1137 Default domain for the function. Should be one of the ``_Domain*`` 

1138 classes. 

1139 fillx : scalar, optional 

1140 Filling value for the first argument, default is 0. 

1141 filly : scalar, optional 

1142 Filling value for the second argument, default is 0. 

1143 

1144 """ 

1145 

1146 def __init__(self, dbfunc, domain, fillx=0, filly=0): 

1147 """abfunc(fillx, filly) must be defined. 

1148 abfunc(x, filly) = x for all x to enable reduce. 

1149 """ 

1150 super().__init__(dbfunc) 

1151 self.domain = domain 

1152 self.fillx = fillx 

1153 self.filly = filly 

1154 ufunc_domain[dbfunc] = domain 

1155 ufunc_fills[dbfunc] = (fillx, filly) 

1156 

1157 def __call__(self, a, b, *args, **kwargs): 

1158 "Execute the call behavior." 

1159 # Get the data 

1160 (da, db) = (getdata(a), getdata(b)) 

1161 # Get the result 

1162 with np.errstate(divide='ignore', invalid='ignore'): 

1163 result = self.f(da, db, *args, **kwargs) 

1164 # Get the mask as a combination of the source masks and invalid 

1165 m = ~umath.isfinite(result) 

1166 m |= getmask(a) 

1167 m |= getmask(b) 

1168 # Apply the domain 

1169 domain = ufunc_domain.get(self.f, None) 

1170 if domain is not None: 

1171 m |= domain(da, db) 

1172 # Take care of the scalar case first 

1173 if not m.ndim: 

1174 if m: 

1175 return masked 

1176 else: 

1177 return result 

1178 # When the mask is True, put back da if possible 

1179 # any errors, just abort; impossible to guarantee masked values 

1180 try: 

1181 np.copyto(result, 0, casting='unsafe', where=m) 

1182 # avoid using "*" since this may be overlaid 

1183 masked_da = umath.multiply(m, da) 

1184 # only add back if it can be cast safely 

1185 if np.can_cast(masked_da.dtype, result.dtype, casting='safe'): 

1186 result += masked_da 

1187 except Exception: 

1188 pass 

1189 

1190 # Transforms to a (subclass of) MaskedArray 

1191 masked_result = result.view(get_masked_subclass(a, b)) 

1192 masked_result._mask = m 

1193 if isinstance(a, MaskedArray): 

1194 masked_result._update_from(a) 

1195 elif isinstance(b, MaskedArray): 

1196 masked_result._update_from(b) 

1197 return masked_result 

1198 

1199 

1200# Unary ufuncs 

1201exp = _MaskedUnaryOperation(umath.exp) 

1202conjugate = _MaskedUnaryOperation(umath.conjugate) 

1203sin = _MaskedUnaryOperation(umath.sin) 

1204cos = _MaskedUnaryOperation(umath.cos) 

1205arctan = _MaskedUnaryOperation(umath.arctan) 

1206arcsinh = _MaskedUnaryOperation(umath.arcsinh) 

1207sinh = _MaskedUnaryOperation(umath.sinh) 

1208cosh = _MaskedUnaryOperation(umath.cosh) 

1209tanh = _MaskedUnaryOperation(umath.tanh) 

1210abs = absolute = _MaskedUnaryOperation(umath.absolute) 

1211angle = _MaskedUnaryOperation(angle) # from numpy.lib.function_base 

1212fabs = _MaskedUnaryOperation(umath.fabs) 

1213negative = _MaskedUnaryOperation(umath.negative) 

1214floor = _MaskedUnaryOperation(umath.floor) 

1215ceil = _MaskedUnaryOperation(umath.ceil) 

1216around = _MaskedUnaryOperation(np.round_) 

1217logical_not = _MaskedUnaryOperation(umath.logical_not) 

1218 

1219# Domained unary ufuncs 

1220sqrt = _MaskedUnaryOperation(umath.sqrt, 0.0, 

1221 _DomainGreaterEqual(0.0)) 

1222log = _MaskedUnaryOperation(umath.log, 1.0, 

1223 _DomainGreater(0.0)) 

1224log2 = _MaskedUnaryOperation(umath.log2, 1.0, 

1225 _DomainGreater(0.0)) 

1226log10 = _MaskedUnaryOperation(umath.log10, 1.0, 

1227 _DomainGreater(0.0)) 

1228tan = _MaskedUnaryOperation(umath.tan, 0.0, 

1229 _DomainTan(1e-35)) 

1230arcsin = _MaskedUnaryOperation(umath.arcsin, 0.0, 

1231 _DomainCheckInterval(-1.0, 1.0)) 

1232arccos = _MaskedUnaryOperation(umath.arccos, 0.0, 

1233 _DomainCheckInterval(-1.0, 1.0)) 

1234arccosh = _MaskedUnaryOperation(umath.arccosh, 1.0, 

1235 _DomainGreaterEqual(1.0)) 

1236arctanh = _MaskedUnaryOperation(umath.arctanh, 0.0, 

1237 _DomainCheckInterval(-1.0 + 1e-15, 1.0 - 1e-15)) 

1238 

1239# Binary ufuncs 

1240add = _MaskedBinaryOperation(umath.add) 

1241subtract = _MaskedBinaryOperation(umath.subtract) 

1242multiply = _MaskedBinaryOperation(umath.multiply, 1, 1) 

1243arctan2 = _MaskedBinaryOperation(umath.arctan2, 0.0, 1.0) 

1244equal = _MaskedBinaryOperation(umath.equal) 

1245equal.reduce = None 

1246not_equal = _MaskedBinaryOperation(umath.not_equal) 

1247not_equal.reduce = None 

1248less_equal = _MaskedBinaryOperation(umath.less_equal) 

1249less_equal.reduce = None 

1250greater_equal = _MaskedBinaryOperation(umath.greater_equal) 

1251greater_equal.reduce = None 

1252less = _MaskedBinaryOperation(umath.less) 

1253less.reduce = None 

1254greater = _MaskedBinaryOperation(umath.greater) 

1255greater.reduce = None 

1256logical_and = _MaskedBinaryOperation(umath.logical_and) 

1257alltrue = _MaskedBinaryOperation(umath.logical_and, 1, 1).reduce 

1258logical_or = _MaskedBinaryOperation(umath.logical_or) 

1259sometrue = logical_or.reduce 

1260logical_xor = _MaskedBinaryOperation(umath.logical_xor) 

1261bitwise_and = _MaskedBinaryOperation(umath.bitwise_and) 

1262bitwise_or = _MaskedBinaryOperation(umath.bitwise_or) 

1263bitwise_xor = _MaskedBinaryOperation(umath.bitwise_xor) 

1264hypot = _MaskedBinaryOperation(umath.hypot) 

1265 

1266# Domained binary ufuncs 

1267divide = _DomainedBinaryOperation(umath.divide, _DomainSafeDivide(), 0, 1) 

1268true_divide = _DomainedBinaryOperation(umath.true_divide, 

1269 _DomainSafeDivide(), 0, 1) 

1270floor_divide = _DomainedBinaryOperation(umath.floor_divide, 

1271 _DomainSafeDivide(), 0, 1) 

1272remainder = _DomainedBinaryOperation(umath.remainder, 

1273 _DomainSafeDivide(), 0, 1) 

1274fmod = _DomainedBinaryOperation(umath.fmod, _DomainSafeDivide(), 0, 1) 

1275mod = _DomainedBinaryOperation(umath.mod, _DomainSafeDivide(), 0, 1) 

1276 

1277 

1278############################################################################### 

1279# Mask creation functions # 

1280############################################################################### 

1281 

1282 

1283def _replace_dtype_fields_recursive(dtype, primitive_dtype): 

1284 "Private function allowing recursion in _replace_dtype_fields." 

1285 _recurse = _replace_dtype_fields_recursive 

1286 

1287 # Do we have some name fields ? 

1288 if dtype.names is not None: 

1289 descr = [] 

1290 for name in dtype.names: 

1291 field = dtype.fields[name] 

1292 if len(field) == 3: 

1293 # Prepend the title to the name 

1294 name = (field[-1], name) 

1295 descr.append((name, _recurse(field[0], primitive_dtype))) 

1296 new_dtype = np.dtype(descr) 

1297 

1298 # Is this some kind of composite a la (float,2) 

1299 elif dtype.subdtype: 

1300 descr = list(dtype.subdtype) 

1301 descr[0] = _recurse(dtype.subdtype[0], primitive_dtype) 

1302 new_dtype = np.dtype(tuple(descr)) 

1303 

1304 # this is a primitive type, so do a direct replacement 

1305 else: 

1306 new_dtype = primitive_dtype 

1307 

1308 # preserve identity of dtypes 

1309 if new_dtype == dtype: 

1310 new_dtype = dtype 

1311 

1312 return new_dtype 

1313 

1314 

1315def _replace_dtype_fields(dtype, primitive_dtype): 

1316 """ 

1317 Construct a dtype description list from a given dtype. 

1318 

1319 Returns a new dtype object, with all fields and subtypes in the given type 

1320 recursively replaced with `primitive_dtype`. 

1321 

1322 Arguments are coerced to dtypes first. 

1323 """ 

1324 dtype = np.dtype(dtype) 

1325 primitive_dtype = np.dtype(primitive_dtype) 

1326 return _replace_dtype_fields_recursive(dtype, primitive_dtype) 

1327 

1328 

1329def make_mask_descr(ndtype): 

1330 """ 

1331 Construct a dtype description list from a given dtype. 

1332 

1333 Returns a new dtype object, with the type of all fields in `ndtype` to a 

1334 boolean type. Field names are not altered. 

1335 

1336 Parameters 

1337 ---------- 

1338 ndtype : dtype 

1339 The dtype to convert. 

1340 

1341 Returns 

1342 ------- 

1343 result : dtype 

1344 A dtype that looks like `ndtype`, the type of all fields is boolean. 

1345 

1346 Examples 

1347 -------- 

1348 >>> import numpy.ma as ma 

1349 >>> dtype = np.dtype({'names':['foo', 'bar'], 

1350 ... 'formats':[np.float32, np.int64]}) 

1351 >>> dtype 

1352 dtype([('foo', '<f4'), ('bar', '<i8')]) 

1353 >>> ma.make_mask_descr(dtype) 

1354 dtype([('foo', '|b1'), ('bar', '|b1')]) 

1355 >>> ma.make_mask_descr(np.float32) 

1356 dtype('bool') 

1357 

1358 """ 

1359 return _replace_dtype_fields(ndtype, MaskType) 

1360 

1361 

1362def getmask(a): 

1363 """ 

1364 Return the mask of a masked array, or nomask. 

1365 

1366 Return the mask of `a` as an ndarray if `a` is a `MaskedArray` and the 

1367 mask is not `nomask`, else return `nomask`. To guarantee a full array 

1368 of booleans of the same shape as a, use `getmaskarray`. 

1369 

1370 Parameters 

1371 ---------- 

1372 a : array_like 

1373 Input `MaskedArray` for which the mask is required. 

1374 

1375 See Also 

1376 -------- 

1377 getdata : Return the data of a masked array as an ndarray. 

1378 getmaskarray : Return the mask of a masked array, or full array of False. 

1379 

1380 Examples 

1381 -------- 

1382 >>> import numpy.ma as ma 

1383 >>> a = ma.masked_equal([[1,2],[3,4]], 2) 

1384 >>> a 

1385 masked_array( 

1386 data=[[1, --], 

1387 [3, 4]], 

1388 mask=[[False, True], 

1389 [False, False]], 

1390 fill_value=2) 

1391 >>> ma.getmask(a) 

1392 array([[False, True], 

1393 [False, False]]) 

1394 

1395 Equivalently use the `MaskedArray` `mask` attribute. 

1396 

1397 >>> a.mask 

1398 array([[False, True], 

1399 [False, False]]) 

1400 

1401 Result when mask == `nomask` 

1402 

1403 >>> b = ma.masked_array([[1,2],[3,4]]) 

1404 >>> b 

1405 masked_array( 

1406 data=[[1, 2], 

1407 [3, 4]], 

1408 mask=False, 

1409 fill_value=999999) 

1410 >>> ma.nomask 

1411 False 

1412 >>> ma.getmask(b) == ma.nomask 

1413 True 

1414 >>> b.mask == ma.nomask 

1415 True 

1416 

1417 """ 

1418 return getattr(a, '_mask', nomask) 

1419 

1420 

1421get_mask = getmask 

1422 

1423 

1424def getmaskarray(arr): 

1425 """ 

1426 Return the mask of a masked array, or full boolean array of False. 

1427 

1428 Return the mask of `arr` as an ndarray if `arr` is a `MaskedArray` and 

1429 the mask is not `nomask`, else return a full boolean array of False of 

1430 the same shape as `arr`. 

1431 

1432 Parameters 

1433 ---------- 

1434 arr : array_like 

1435 Input `MaskedArray` for which the mask is required. 

1436 

1437 See Also 

1438 -------- 

1439 getmask : Return the mask of a masked array, or nomask. 

1440 getdata : Return the data of a masked array as an ndarray. 

1441 

1442 Examples 

1443 -------- 

1444 >>> import numpy.ma as ma 

1445 >>> a = ma.masked_equal([[1,2],[3,4]], 2) 

1446 >>> a 

1447 masked_array( 

1448 data=[[1, --], 

1449 [3, 4]], 

1450 mask=[[False, True], 

1451 [False, False]], 

1452 fill_value=2) 

1453 >>> ma.getmaskarray(a) 

1454 array([[False, True], 

1455 [False, False]]) 

1456 

1457 Result when mask == ``nomask`` 

1458 

1459 >>> b = ma.masked_array([[1,2],[3,4]]) 

1460 >>> b 

1461 masked_array( 

1462 data=[[1, 2], 

1463 [3, 4]], 

1464 mask=False, 

1465 fill_value=999999) 

1466 >>> ma.getmaskarray(b) 

1467 array([[False, False], 

1468 [False, False]]) 

1469 

1470 """ 

1471 mask = getmask(arr) 

1472 if mask is nomask: 

1473 mask = make_mask_none(np.shape(arr), getattr(arr, 'dtype', None)) 

1474 return mask 

1475 

1476 

1477def is_mask(m): 

1478 """ 

1479 Return True if m is a valid, standard mask. 

1480 

1481 This function does not check the contents of the input, only that the 

1482 type is MaskType. In particular, this function returns False if the 

1483 mask has a flexible dtype. 

1484 

1485 Parameters 

1486 ---------- 

1487 m : array_like 

1488 Array to test. 

1489 

1490 Returns 

1491 ------- 

1492 result : bool 

1493 True if `m.dtype.type` is MaskType, False otherwise. 

1494 

1495 See Also 

1496 -------- 

1497 ma.isMaskedArray : Test whether input is an instance of MaskedArray. 

1498 

1499 Examples 

1500 -------- 

1501 >>> import numpy.ma as ma 

1502 >>> m = ma.masked_equal([0, 1, 0, 2, 3], 0) 

1503 >>> m 

1504 masked_array(data=[--, 1, --, 2, 3], 

1505 mask=[ True, False, True, False, False], 

1506 fill_value=0) 

1507 >>> ma.is_mask(m) 

1508 False 

1509 >>> ma.is_mask(m.mask) 

1510 True 

1511 

1512 Input must be an ndarray (or have similar attributes) 

1513 for it to be considered a valid mask. 

1514 

1515 >>> m = [False, True, False] 

1516 >>> ma.is_mask(m) 

1517 False 

1518 >>> m = np.array([False, True, False]) 

1519 >>> m 

1520 array([False, True, False]) 

1521 >>> ma.is_mask(m) 

1522 True 

1523 

1524 Arrays with complex dtypes don't return True. 

1525 

1526 >>> dtype = np.dtype({'names':['monty', 'pithon'], 

1527 ... 'formats':[bool, bool]}) 

1528 >>> dtype 

1529 dtype([('monty', '|b1'), ('pithon', '|b1')]) 

1530 >>> m = np.array([(True, False), (False, True), (True, False)], 

1531 ... dtype=dtype) 

1532 >>> m 

1533 array([( True, False), (False, True), ( True, False)], 

1534 dtype=[('monty', '?'), ('pithon', '?')]) 

1535 >>> ma.is_mask(m) 

1536 False 

1537 

1538 """ 

1539 try: 

1540 return m.dtype.type is MaskType 

1541 except AttributeError: 

1542 return False 

1543 

1544 

1545def _shrink_mask(m): 

1546 """ 

1547 Shrink a mask to nomask if possible 

1548 """ 

1549 if m.dtype.names is None and not m.any(): 

1550 return nomask 

1551 else: 

1552 return m 

1553 

1554 

1555def make_mask(m, copy=False, shrink=True, dtype=MaskType): 

1556 """ 

1557 Create a boolean mask from an array. 

1558 

1559 Return `m` as a boolean mask, creating a copy if necessary or requested. 

1560 The function can accept any sequence that is convertible to integers, 

1561 or ``nomask``. Does not require that contents must be 0s and 1s, values 

1562 of 0 are interpreted as False, everything else as True. 

1563 

1564 Parameters 

1565 ---------- 

1566 m : array_like 

1567 Potential mask. 

1568 copy : bool, optional 

1569 Whether to return a copy of `m` (True) or `m` itself (False). 

1570 shrink : bool, optional 

1571 Whether to shrink `m` to ``nomask`` if all its values are False. 

1572 dtype : dtype, optional 

1573 Data-type of the output mask. By default, the output mask has a 

1574 dtype of MaskType (bool). If the dtype is flexible, each field has 

1575 a boolean dtype. This is ignored when `m` is ``nomask``, in which 

1576 case ``nomask`` is always returned. 

1577 

1578 Returns 

1579 ------- 

1580 result : ndarray 

1581 A boolean mask derived from `m`. 

1582 

1583 Examples 

1584 -------- 

1585 >>> import numpy.ma as ma 

1586 >>> m = [True, False, True, True] 

1587 >>> ma.make_mask(m) 

1588 array([ True, False, True, True]) 

1589 >>> m = [1, 0, 1, 1] 

1590 >>> ma.make_mask(m) 

1591 array([ True, False, True, True]) 

1592 >>> m = [1, 0, 2, -3] 

1593 >>> ma.make_mask(m) 

1594 array([ True, False, True, True]) 

1595 

1596 Effect of the `shrink` parameter. 

1597 

1598 >>> m = np.zeros(4) 

1599 >>> m 

1600 array([0., 0., 0., 0.]) 

1601 >>> ma.make_mask(m) 

1602 False 

1603 >>> ma.make_mask(m, shrink=False) 

1604 array([False, False, False, False]) 

1605 

1606 Using a flexible `dtype`. 

1607 

1608 >>> m = [1, 0, 1, 1] 

1609 >>> n = [0, 1, 0, 0] 

1610 >>> arr = [] 

1611 >>> for man, mouse in zip(m, n): 

1612 ... arr.append((man, mouse)) 

1613 >>> arr 

1614 [(1, 0), (0, 1), (1, 0), (1, 0)] 

1615 >>> dtype = np.dtype({'names':['man', 'mouse'], 

1616 ... 'formats':[np.int64, np.int64]}) 

1617 >>> arr = np.array(arr, dtype=dtype) 

1618 >>> arr 

1619 array([(1, 0), (0, 1), (1, 0), (1, 0)], 

1620 dtype=[('man', '<i8'), ('mouse', '<i8')]) 

1621 >>> ma.make_mask(arr, dtype=dtype) 

1622 array([(True, False), (False, True), (True, False), (True, False)], 

1623 dtype=[('man', '|b1'), ('mouse', '|b1')]) 

1624 

1625 """ 

1626 if m is nomask: 

1627 return nomask 

1628 

1629 # Make sure the input dtype is valid. 

1630 dtype = make_mask_descr(dtype) 

1631 

1632 # legacy boolean special case: "existence of fields implies true" 

1633 if isinstance(m, ndarray) and m.dtype.fields and dtype == np.bool_: 

1634 return np.ones(m.shape, dtype=dtype) 

1635 

1636 # Fill the mask in case there are missing data; turn it into an ndarray. 

1637 result = np.array(filled(m, True), copy=copy, dtype=dtype, subok=True) 

1638 # Bas les masques ! 

1639 if shrink: 

1640 result = _shrink_mask(result) 

1641 return result 

1642 

1643 

1644def make_mask_none(newshape, dtype=None): 

1645 """ 

1646 Return a boolean mask of the given shape, filled with False. 

1647 

1648 This function returns a boolean ndarray with all entries False, that can 

1649 be used in common mask manipulations. If a complex dtype is specified, the 

1650 type of each field is converted to a boolean type. 

1651 

1652 Parameters 

1653 ---------- 

1654 newshape : tuple 

1655 A tuple indicating the shape of the mask. 

1656 dtype : {None, dtype}, optional 

1657 If None, use a MaskType instance. Otherwise, use a new datatype with 

1658 the same fields as `dtype`, converted to boolean types. 

1659 

1660 Returns 

1661 ------- 

1662 result : ndarray 

1663 An ndarray of appropriate shape and dtype, filled with False. 

1664 

1665 See Also 

1666 -------- 

1667 make_mask : Create a boolean mask from an array. 

1668 make_mask_descr : Construct a dtype description list from a given dtype. 

1669 

1670 Examples 

1671 -------- 

1672 >>> import numpy.ma as ma 

1673 >>> ma.make_mask_none((3,)) 

1674 array([False, False, False]) 

1675 

1676 Defining a more complex dtype. 

1677 

1678 >>> dtype = np.dtype({'names':['foo', 'bar'], 

1679 ... 'formats':[np.float32, np.int64]}) 

1680 >>> dtype 

1681 dtype([('foo', '<f4'), ('bar', '<i8')]) 

1682 >>> ma.make_mask_none((3,), dtype=dtype) 

1683 array([(False, False), (False, False), (False, False)], 

1684 dtype=[('foo', '|b1'), ('bar', '|b1')]) 

1685 

1686 """ 

1687 if dtype is None: 

1688 result = np.zeros(newshape, dtype=MaskType) 

1689 else: 

1690 result = np.zeros(newshape, dtype=make_mask_descr(dtype)) 

1691 return result 

1692 

1693 

1694def _recursive_mask_or(m1, m2, newmask): 

1695 names = m1.dtype.names 

1696 for name in names: 

1697 current1 = m1[name] 

1698 if current1.dtype.names is not None: 

1699 _recursive_mask_or(current1, m2[name], newmask[name]) 

1700 else: 

1701 umath.logical_or(current1, m2[name], newmask[name]) 

1702 

1703 

1704def mask_or(m1, m2, copy=False, shrink=True): 

1705 """ 

1706 Combine two masks with the ``logical_or`` operator. 

1707 

1708 The result may be a view on `m1` or `m2` if the other is `nomask` 

1709 (i.e. False). 

1710 

1711 Parameters 

1712 ---------- 

1713 m1, m2 : array_like 

1714 Input masks. 

1715 copy : bool, optional 

1716 If copy is False and one of the inputs is `nomask`, return a view 

1717 of the other input mask. Defaults to False. 

1718 shrink : bool, optional 

1719 Whether to shrink the output to `nomask` if all its values are 

1720 False. Defaults to True. 

1721 

1722 Returns 

1723 ------- 

1724 mask : output mask 

1725 The result masks values that are masked in either `m1` or `m2`. 

1726 

1727 Raises 

1728 ------ 

1729 ValueError 

1730 If `m1` and `m2` have different flexible dtypes. 

1731 

1732 Examples 

1733 -------- 

1734 >>> m1 = np.ma.make_mask([0, 1, 1, 0]) 

1735 >>> m2 = np.ma.make_mask([1, 0, 0, 0]) 

1736 >>> np.ma.mask_or(m1, m2) 

1737 array([ True, True, True, False]) 

1738 

1739 """ 

1740 

1741 if (m1 is nomask) or (m1 is False): 

1742 dtype = getattr(m2, 'dtype', MaskType) 

1743 return make_mask(m2, copy=copy, shrink=shrink, dtype=dtype) 

1744 if (m2 is nomask) or (m2 is False): 

1745 dtype = getattr(m1, 'dtype', MaskType) 

1746 return make_mask(m1, copy=copy, shrink=shrink, dtype=dtype) 

1747 if m1 is m2 and is_mask(m1): 

1748 return m1 

1749 (dtype1, dtype2) = (getattr(m1, 'dtype', None), getattr(m2, 'dtype', None)) 

1750 if dtype1 != dtype2: 

1751 raise ValueError("Incompatible dtypes '%s'<>'%s'" % (dtype1, dtype2)) 

1752 if dtype1.names is not None: 

1753 # Allocate an output mask array with the properly broadcast shape. 

1754 newmask = np.empty(np.broadcast(m1, m2).shape, dtype1) 

1755 _recursive_mask_or(m1, m2, newmask) 

1756 return newmask 

1757 return make_mask(umath.logical_or(m1, m2), copy=copy, shrink=shrink) 

1758 

1759 

1760def flatten_mask(mask): 

1761 """ 

1762 Returns a completely flattened version of the mask, where nested fields 

1763 are collapsed. 

1764 

1765 Parameters 

1766 ---------- 

1767 mask : array_like 

1768 Input array, which will be interpreted as booleans. 

1769 

1770 Returns 

1771 ------- 

1772 flattened_mask : ndarray of bools 

1773 The flattened input. 

1774 

1775 Examples 

1776 -------- 

1777 >>> mask = np.array([0, 0, 1]) 

1778 >>> np.ma.flatten_mask(mask) 

1779 array([False, False, True]) 

1780 

1781 >>> mask = np.array([(0, 0), (0, 1)], dtype=[('a', bool), ('b', bool)]) 

1782 >>> np.ma.flatten_mask(mask) 

1783 array([False, False, False, True]) 

1784 

1785 >>> mdtype = [('a', bool), ('b', [('ba', bool), ('bb', bool)])] 

1786 >>> mask = np.array([(0, (0, 0)), (0, (0, 1))], dtype=mdtype) 

1787 >>> np.ma.flatten_mask(mask) 

1788 array([False, False, False, False, False, True]) 

1789 

1790 """ 

1791 

1792 def _flatmask(mask): 

1793 "Flatten the mask and returns a (maybe nested) sequence of booleans." 

1794 mnames = mask.dtype.names 

1795 if mnames is not None: 

1796 return [flatten_mask(mask[name]) for name in mnames] 

1797 else: 

1798 return mask 

1799 

1800 def _flatsequence(sequence): 

1801 "Generates a flattened version of the sequence." 

1802 try: 

1803 for element in sequence: 

1804 if hasattr(element, '__iter__'): 

1805 yield from _flatsequence(element) 

1806 else: 

1807 yield element 

1808 except TypeError: 

1809 yield sequence 

1810 

1811 mask = np.asarray(mask) 

1812 flattened = _flatsequence(_flatmask(mask)) 

1813 return np.array([_ for _ in flattened], dtype=bool) 

1814 

1815 

1816def _check_mask_axis(mask, axis, keepdims=np._NoValue): 

1817 "Check whether there are masked values along the given axis" 

1818 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

1819 if mask is not nomask: 

1820 return mask.all(axis=axis, **kwargs) 

1821 return nomask 

1822 

1823 

1824############################################################################### 

1825# Masking functions # 

1826############################################################################### 

1827 

1828def masked_where(condition, a, copy=True): 

1829 """ 

1830 Mask an array where a condition is met. 

1831 

1832 Return `a` as an array masked where `condition` is True. 

1833 Any masked values of `a` or `condition` are also masked in the output. 

1834 

1835 Parameters 

1836 ---------- 

1837 condition : array_like 

1838 Masking condition. When `condition` tests floating point values for 

1839 equality, consider using ``masked_values`` instead. 

1840 a : array_like 

1841 Array to mask. 

1842 copy : bool 

1843 If True (default) make a copy of `a` in the result. If False modify 

1844 `a` in place and return a view. 

1845 

1846 Returns 

1847 ------- 

1848 result : MaskedArray 

1849 The result of masking `a` where `condition` is True. 

1850 

1851 See Also 

1852 -------- 

1853 masked_values : Mask using floating point equality. 

1854 masked_equal : Mask where equal to a given value. 

1855 masked_not_equal : Mask where `not` equal to a given value. 

1856 masked_less_equal : Mask where less than or equal to a given value. 

1857 masked_greater_equal : Mask where greater than or equal to a given value. 

1858 masked_less : Mask where less than a given value. 

1859 masked_greater : Mask where greater than a given value. 

1860 masked_inside : Mask inside a given interval. 

1861 masked_outside : Mask outside a given interval. 

1862 masked_invalid : Mask invalid values (NaNs or infs). 

1863 

1864 Examples 

1865 -------- 

1866 >>> import numpy.ma as ma 

1867 >>> a = np.arange(4) 

1868 >>> a 

1869 array([0, 1, 2, 3]) 

1870 >>> ma.masked_where(a <= 2, a) 

1871 masked_array(data=[--, --, --, 3], 

1872 mask=[ True, True, True, False], 

1873 fill_value=999999) 

1874 

1875 Mask array `b` conditional on `a`. 

1876 

1877 >>> b = ['a', 'b', 'c', 'd'] 

1878 >>> ma.masked_where(a == 2, b) 

1879 masked_array(data=['a', 'b', --, 'd'], 

1880 mask=[False, False, True, False], 

1881 fill_value='N/A', 

1882 dtype='<U1') 

1883 

1884 Effect of the `copy` argument. 

1885 

1886 >>> c = ma.masked_where(a <= 2, a) 

1887 >>> c 

1888 masked_array(data=[--, --, --, 3], 

1889 mask=[ True, True, True, False], 

1890 fill_value=999999) 

1891 >>> c[0] = 99 

1892 >>> c 

1893 masked_array(data=[99, --, --, 3], 

1894 mask=[False, True, True, False], 

1895 fill_value=999999) 

1896 >>> a 

1897 array([0, 1, 2, 3]) 

1898 >>> c = ma.masked_where(a <= 2, a, copy=False) 

1899 >>> c[0] = 99 

1900 >>> c 

1901 masked_array(data=[99, --, --, 3], 

1902 mask=[False, True, True, False], 

1903 fill_value=999999) 

1904 >>> a 

1905 array([99, 1, 2, 3]) 

1906 

1907 When `condition` or `a` contain masked values. 

1908 

1909 >>> a = np.arange(4) 

1910 >>> a = ma.masked_where(a == 2, a) 

1911 >>> a 

1912 masked_array(data=[0, 1, --, 3], 

1913 mask=[False, False, True, False], 

1914 fill_value=999999) 

1915 >>> b = np.arange(4) 

1916 >>> b = ma.masked_where(b == 0, b) 

1917 >>> b 

1918 masked_array(data=[--, 1, 2, 3], 

1919 mask=[ True, False, False, False], 

1920 fill_value=999999) 

1921 >>> ma.masked_where(a == 3, b) 

1922 masked_array(data=[--, 1, --, --], 

1923 mask=[ True, False, True, True], 

1924 fill_value=999999) 

1925 

1926 """ 

1927 # Make sure that condition is a valid standard-type mask. 

1928 cond = make_mask(condition, shrink=False) 

1929 a = np.array(a, copy=copy, subok=True) 

1930 

1931 (cshape, ashape) = (cond.shape, a.shape) 

1932 if cshape and cshape != ashape: 

1933 raise IndexError("Inconsistent shape between the condition and the input" 

1934 " (got %s and %s)" % (cshape, ashape)) 

1935 if hasattr(a, '_mask'): 

1936 cond = mask_or(cond, a._mask) 

1937 cls = type(a) 

1938 else: 

1939 cls = MaskedArray 

1940 result = a.view(cls) 

1941 # Assign to *.mask so that structured masks are handled correctly. 

1942 result.mask = _shrink_mask(cond) 

1943 # There is no view of a boolean so when 'a' is a MaskedArray with nomask 

1944 # the update to the result's mask has no effect. 

1945 if not copy and hasattr(a, '_mask') and getmask(a) is nomask: 

1946 a._mask = result._mask.view() 

1947 return result 

1948 

1949 

1950def masked_greater(x, value, copy=True): 

1951 """ 

1952 Mask an array where greater than a given value. 

1953 

1954 This function is a shortcut to ``masked_where``, with 

1955 `condition` = (x > value). 

1956 

1957 See Also 

1958 -------- 

1959 masked_where : Mask where a condition is met. 

1960 

1961 Examples 

1962 -------- 

1963 >>> import numpy.ma as ma 

1964 >>> a = np.arange(4) 

1965 >>> a 

1966 array([0, 1, 2, 3]) 

1967 >>> ma.masked_greater(a, 2) 

1968 masked_array(data=[0, 1, 2, --], 

1969 mask=[False, False, False, True], 

1970 fill_value=999999) 

1971 

1972 """ 

1973 return masked_where(greater(x, value), x, copy=copy) 

1974 

1975 

1976def masked_greater_equal(x, value, copy=True): 

1977 """ 

1978 Mask an array where greater than or equal to a given value. 

1979 

1980 This function is a shortcut to ``masked_where``, with 

1981 `condition` = (x >= value). 

1982 

1983 See Also 

1984 -------- 

1985 masked_where : Mask where a condition is met. 

1986 

1987 Examples 

1988 -------- 

1989 >>> import numpy.ma as ma 

1990 >>> a = np.arange(4) 

1991 >>> a 

1992 array([0, 1, 2, 3]) 

1993 >>> ma.masked_greater_equal(a, 2) 

1994 masked_array(data=[0, 1, --, --], 

1995 mask=[False, False, True, True], 

1996 fill_value=999999) 

1997 

1998 """ 

1999 return masked_where(greater_equal(x, value), x, copy=copy) 

2000 

2001 

2002def masked_less(x, value, copy=True): 

2003 """ 

2004 Mask an array where less than a given value. 

2005 

2006 This function is a shortcut to ``masked_where``, with 

2007 `condition` = (x < value). 

2008 

2009 See Also 

2010 -------- 

2011 masked_where : Mask where a condition is met. 

2012 

2013 Examples 

2014 -------- 

2015 >>> import numpy.ma as ma 

2016 >>> a = np.arange(4) 

2017 >>> a 

2018 array([0, 1, 2, 3]) 

2019 >>> ma.masked_less(a, 2) 

2020 masked_array(data=[--, --, 2, 3], 

2021 mask=[ True, True, False, False], 

2022 fill_value=999999) 

2023 

2024 """ 

2025 return masked_where(less(x, value), x, copy=copy) 

2026 

2027 

2028def masked_less_equal(x, value, copy=True): 

2029 """ 

2030 Mask an array where less than or equal to a given value. 

2031 

2032 This function is a shortcut to ``masked_where``, with 

2033 `condition` = (x <= value). 

2034 

2035 See Also 

2036 -------- 

2037 masked_where : Mask where a condition is met. 

2038 

2039 Examples 

2040 -------- 

2041 >>> import numpy.ma as ma 

2042 >>> a = np.arange(4) 

2043 >>> a 

2044 array([0, 1, 2, 3]) 

2045 >>> ma.masked_less_equal(a, 2) 

2046 masked_array(data=[--, --, --, 3], 

2047 mask=[ True, True, True, False], 

2048 fill_value=999999) 

2049 

2050 """ 

2051 return masked_where(less_equal(x, value), x, copy=copy) 

2052 

2053 

2054def masked_not_equal(x, value, copy=True): 

2055 """ 

2056 Mask an array where `not` equal to a given value. 

2057 

2058 This function is a shortcut to ``masked_where``, with 

2059 `condition` = (x != value). 

2060 

2061 See Also 

2062 -------- 

2063 masked_where : Mask where a condition is met. 

2064 

2065 Examples 

2066 -------- 

2067 >>> import numpy.ma as ma 

2068 >>> a = np.arange(4) 

2069 >>> a 

2070 array([0, 1, 2, 3]) 

2071 >>> ma.masked_not_equal(a, 2) 

2072 masked_array(data=[--, --, 2, --], 

2073 mask=[ True, True, False, True], 

2074 fill_value=999999) 

2075 

2076 """ 

2077 return masked_where(not_equal(x, value), x, copy=copy) 

2078 

2079 

2080def masked_equal(x, value, copy=True): 

2081 """ 

2082 Mask an array where equal to a given value. 

2083 

2084 Return a MaskedArray, masked where the data in array `x` are 

2085 equal to `value`. The fill_value of the returned MaskedArray 

2086 is set to `value`. 

2087 

2088 For floating point arrays, consider using ``masked_values(x, value)``. 

2089 

2090 See Also 

2091 -------- 

2092 masked_where : Mask where a condition is met. 

2093 masked_values : Mask using floating point equality. 

2094 

2095 Examples 

2096 -------- 

2097 >>> import numpy.ma as ma 

2098 >>> a = np.arange(4) 

2099 >>> a 

2100 array([0, 1, 2, 3]) 

2101 >>> ma.masked_equal(a, 2) 

2102 masked_array(data=[0, 1, --, 3], 

2103 mask=[False, False, True, False], 

2104 fill_value=2) 

2105 

2106 """ 

2107 output = masked_where(equal(x, value), x, copy=copy) 

2108 output.fill_value = value 

2109 return output 

2110 

2111 

2112def masked_inside(x, v1, v2, copy=True): 

2113 """ 

2114 Mask an array inside a given interval. 

2115 

2116 Shortcut to ``masked_where``, where `condition` is True for `x` inside 

2117 the interval [v1,v2] (v1 <= x <= v2). The boundaries `v1` and `v2` 

2118 can be given in either order. 

2119 

2120 See Also 

2121 -------- 

2122 masked_where : Mask where a condition is met. 

2123 

2124 Notes 

2125 ----- 

2126 The array `x` is prefilled with its filling value. 

2127 

2128 Examples 

2129 -------- 

2130 >>> import numpy.ma as ma 

2131 >>> x = [0.31, 1.2, 0.01, 0.2, -0.4, -1.1] 

2132 >>> ma.masked_inside(x, -0.3, 0.3) 

2133 masked_array(data=[0.31, 1.2, --, --, -0.4, -1.1], 

2134 mask=[False, False, True, True, False, False], 

2135 fill_value=1e+20) 

2136 

2137 The order of `v1` and `v2` doesn't matter. 

2138 

2139 >>> ma.masked_inside(x, 0.3, -0.3) 

2140 masked_array(data=[0.31, 1.2, --, --, -0.4, -1.1], 

2141 mask=[False, False, True, True, False, False], 

2142 fill_value=1e+20) 

2143 

2144 """ 

2145 if v2 < v1: 

2146 (v1, v2) = (v2, v1) 

2147 xf = filled(x) 

2148 condition = (xf >= v1) & (xf <= v2) 

2149 return masked_where(condition, x, copy=copy) 

2150 

2151 

2152def masked_outside(x, v1, v2, copy=True): 

2153 """ 

2154 Mask an array outside a given interval. 

2155 

2156 Shortcut to ``masked_where``, where `condition` is True for `x` outside 

2157 the interval [v1,v2] (x < v1)|(x > v2). 

2158 The boundaries `v1` and `v2` can be given in either order. 

2159 

2160 See Also 

2161 -------- 

2162 masked_where : Mask where a condition is met. 

2163 

2164 Notes 

2165 ----- 

2166 The array `x` is prefilled with its filling value. 

2167 

2168 Examples 

2169 -------- 

2170 >>> import numpy.ma as ma 

2171 >>> x = [0.31, 1.2, 0.01, 0.2, -0.4, -1.1] 

2172 >>> ma.masked_outside(x, -0.3, 0.3) 

2173 masked_array(data=[--, --, 0.01, 0.2, --, --], 

2174 mask=[ True, True, False, False, True, True], 

2175 fill_value=1e+20) 

2176 

2177 The order of `v1` and `v2` doesn't matter. 

2178 

2179 >>> ma.masked_outside(x, 0.3, -0.3) 

2180 masked_array(data=[--, --, 0.01, 0.2, --, --], 

2181 mask=[ True, True, False, False, True, True], 

2182 fill_value=1e+20) 

2183 

2184 """ 

2185 if v2 < v1: 

2186 (v1, v2) = (v2, v1) 

2187 xf = filled(x) 

2188 condition = (xf < v1) | (xf > v2) 

2189 return masked_where(condition, x, copy=copy) 

2190 

2191 

2192def masked_object(x, value, copy=True, shrink=True): 

2193 """ 

2194 Mask the array `x` where the data are exactly equal to value. 

2195 

2196 This function is similar to `masked_values`, but only suitable 

2197 for object arrays: for floating point, use `masked_values` instead. 

2198 

2199 Parameters 

2200 ---------- 

2201 x : array_like 

2202 Array to mask 

2203 value : object 

2204 Comparison value 

2205 copy : {True, False}, optional 

2206 Whether to return a copy of `x`. 

2207 shrink : {True, False}, optional 

2208 Whether to collapse a mask full of False to nomask 

2209 

2210 Returns 

2211 ------- 

2212 result : MaskedArray 

2213 The result of masking `x` where equal to `value`. 

2214 

2215 See Also 

2216 -------- 

2217 masked_where : Mask where a condition is met. 

2218 masked_equal : Mask where equal to a given value (integers). 

2219 masked_values : Mask using floating point equality. 

2220 

2221 Examples 

2222 -------- 

2223 >>> import numpy.ma as ma 

2224 >>> food = np.array(['green_eggs', 'ham'], dtype=object) 

2225 >>> # don't eat spoiled food 

2226 >>> eat = ma.masked_object(food, 'green_eggs') 

2227 >>> eat 

2228 masked_array(data=[--, 'ham'], 

2229 mask=[ True, False], 

2230 fill_value='green_eggs', 

2231 dtype=object) 

2232 >>> # plain ol` ham is boring 

2233 >>> fresh_food = np.array(['cheese', 'ham', 'pineapple'], dtype=object) 

2234 >>> eat = ma.masked_object(fresh_food, 'green_eggs') 

2235 >>> eat 

2236 masked_array(data=['cheese', 'ham', 'pineapple'], 

2237 mask=False, 

2238 fill_value='green_eggs', 

2239 dtype=object) 

2240 

2241 Note that `mask` is set to ``nomask`` if possible. 

2242 

2243 >>> eat 

2244 masked_array(data=['cheese', 'ham', 'pineapple'], 

2245 mask=False, 

2246 fill_value='green_eggs', 

2247 dtype=object) 

2248 

2249 """ 

2250 if isMaskedArray(x): 

2251 condition = umath.equal(x._data, value) 

2252 mask = x._mask 

2253 else: 

2254 condition = umath.equal(np.asarray(x), value) 

2255 mask = nomask 

2256 mask = mask_or(mask, make_mask(condition, shrink=shrink)) 

2257 return masked_array(x, mask=mask, copy=copy, fill_value=value) 

2258 

2259 

2260def masked_values(x, value, rtol=1e-5, atol=1e-8, copy=True, shrink=True): 

2261 """ 

2262 Mask using floating point equality. 

2263 

2264 Return a MaskedArray, masked where the data in array `x` are approximately 

2265 equal to `value`, determined using `isclose`. The default tolerances for 

2266 `masked_values` are the same as those for `isclose`. 

2267 

2268 For integer types, exact equality is used, in the same way as 

2269 `masked_equal`. 

2270 

2271 The fill_value is set to `value` and the mask is set to ``nomask`` if 

2272 possible. 

2273 

2274 Parameters 

2275 ---------- 

2276 x : array_like 

2277 Array to mask. 

2278 value : float 

2279 Masking value. 

2280 rtol, atol : float, optional 

2281 Tolerance parameters passed on to `isclose` 

2282 copy : bool, optional 

2283 Whether to return a copy of `x`. 

2284 shrink : bool, optional 

2285 Whether to collapse a mask full of False to ``nomask``. 

2286 

2287 Returns 

2288 ------- 

2289 result : MaskedArray 

2290 The result of masking `x` where approximately equal to `value`. 

2291 

2292 See Also 

2293 -------- 

2294 masked_where : Mask where a condition is met. 

2295 masked_equal : Mask where equal to a given value (integers). 

2296 

2297 Examples 

2298 -------- 

2299 >>> import numpy.ma as ma 

2300 >>> x = np.array([1, 1.1, 2, 1.1, 3]) 

2301 >>> ma.masked_values(x, 1.1) 

2302 masked_array(data=[1.0, --, 2.0, --, 3.0], 

2303 mask=[False, True, False, True, False], 

2304 fill_value=1.1) 

2305 

2306 Note that `mask` is set to ``nomask`` if possible. 

2307 

2308 >>> ma.masked_values(x, 2.1) 

2309 masked_array(data=[1. , 1.1, 2. , 1.1, 3. ], 

2310 mask=False, 

2311 fill_value=2.1) 

2312 

2313 Unlike `masked_equal`, `masked_values` can perform approximate equalities. 

2314 

2315 >>> ma.masked_values(x, 2.1, atol=1e-1) 

2316 masked_array(data=[1.0, 1.1, --, 1.1, 3.0], 

2317 mask=[False, False, True, False, False], 

2318 fill_value=2.1) 

2319 

2320 """ 

2321 xnew = filled(x, value) 

2322 if np.issubdtype(xnew.dtype, np.floating): 

2323 mask = np.isclose(xnew, value, atol=atol, rtol=rtol) 

2324 else: 

2325 mask = umath.equal(xnew, value) 

2326 ret = masked_array(xnew, mask=mask, copy=copy, fill_value=value) 

2327 if shrink: 

2328 ret.shrink_mask() 

2329 return ret 

2330 

2331 

2332def masked_invalid(a, copy=True): 

2333 """ 

2334 Mask an array where invalid values occur (NaNs or infs). 

2335 

2336 This function is a shortcut to ``masked_where``, with 

2337 `condition` = ~(np.isfinite(a)). Any pre-existing mask is conserved. 

2338 Only applies to arrays with a dtype where NaNs or infs make sense 

2339 (i.e. floating point types), but accepts any array_like object. 

2340 

2341 See Also 

2342 -------- 

2343 masked_where : Mask where a condition is met. 

2344 

2345 Examples 

2346 -------- 

2347 >>> import numpy.ma as ma 

2348 >>> a = np.arange(5, dtype=float) 

2349 >>> a[2] = np.NaN 

2350 >>> a[3] = np.PINF 

2351 >>> a 

2352 array([ 0., 1., nan, inf, 4.]) 

2353 >>> ma.masked_invalid(a) 

2354 masked_array(data=[0.0, 1.0, --, --, 4.0], 

2355 mask=[False, False, True, True, False], 

2356 fill_value=1e+20) 

2357 

2358 """ 

2359 a = np.array(a, copy=False, subok=True) 

2360 res = masked_where(~(np.isfinite(a)), a, copy=copy) 

2361 # masked_invalid previously never returned nomask as a mask and doing so 

2362 # threw off matplotlib (gh-22842). So use shrink=False: 

2363 if res._mask is nomask: 

2364 res._mask = make_mask_none(res.shape, res.dtype) 

2365 return res 

2366 

2367############################################################################### 

2368# Printing options # 

2369############################################################################### 

2370 

2371 

2372class _MaskedPrintOption: 

2373 """ 

2374 Handle the string used to represent missing data in a masked array. 

2375 

2376 """ 

2377 

2378 def __init__(self, display): 

2379 """ 

2380 Create the masked_print_option object. 

2381 

2382 """ 

2383 self._display = display 

2384 self._enabled = True 

2385 

2386 def display(self): 

2387 """ 

2388 Display the string to print for masked values. 

2389 

2390 """ 

2391 return self._display 

2392 

2393 def set_display(self, s): 

2394 """ 

2395 Set the string to print for masked values. 

2396 

2397 """ 

2398 self._display = s 

2399 

2400 def enabled(self): 

2401 """ 

2402 Is the use of the display value enabled? 

2403 

2404 """ 

2405 return self._enabled 

2406 

2407 def enable(self, shrink=1): 

2408 """ 

2409 Set the enabling shrink to `shrink`. 

2410 

2411 """ 

2412 self._enabled = shrink 

2413 

2414 def __str__(self): 

2415 return str(self._display) 

2416 

2417 __repr__ = __str__ 

2418 

2419# if you single index into a masked location you get this object. 

2420masked_print_option = _MaskedPrintOption('--') 

2421 

2422 

2423def _recursive_printoption(result, mask, printopt): 

2424 """ 

2425 Puts printoptions in result where mask is True. 

2426 

2427 Private function allowing for recursion 

2428 

2429 """ 

2430 names = result.dtype.names 

2431 if names is not None: 

2432 for name in names: 

2433 curdata = result[name] 

2434 curmask = mask[name] 

2435 _recursive_printoption(curdata, curmask, printopt) 

2436 else: 

2437 np.copyto(result, printopt, where=mask) 

2438 return 

2439 

2440# For better or worse, these end in a newline 

2441_legacy_print_templates = dict( 

2442 long_std=textwrap.dedent("""\ 

2443 masked_%(name)s(data = 

2444 %(data)s, 

2445 %(nlen)s mask = 

2446 %(mask)s, 

2447 %(nlen)s fill_value = %(fill)s) 

2448 """), 

2449 long_flx=textwrap.dedent("""\ 

2450 masked_%(name)s(data = 

2451 %(data)s, 

2452 %(nlen)s mask = 

2453 %(mask)s, 

2454 %(nlen)s fill_value = %(fill)s, 

2455 %(nlen)s dtype = %(dtype)s) 

2456 """), 

2457 short_std=textwrap.dedent("""\ 

2458 masked_%(name)s(data = %(data)s, 

2459 %(nlen)s mask = %(mask)s, 

2460 %(nlen)s fill_value = %(fill)s) 

2461 """), 

2462 short_flx=textwrap.dedent("""\ 

2463 masked_%(name)s(data = %(data)s, 

2464 %(nlen)s mask = %(mask)s, 

2465 %(nlen)s fill_value = %(fill)s, 

2466 %(nlen)s dtype = %(dtype)s) 

2467 """) 

2468) 

2469 

2470############################################################################### 

2471# MaskedArray class # 

2472############################################################################### 

2473 

2474 

2475def _recursive_filled(a, mask, fill_value): 

2476 """ 

2477 Recursively fill `a` with `fill_value`. 

2478 

2479 """ 

2480 names = a.dtype.names 

2481 for name in names: 

2482 current = a[name] 

2483 if current.dtype.names is not None: 

2484 _recursive_filled(current, mask[name], fill_value[name]) 

2485 else: 

2486 np.copyto(current, fill_value[name], where=mask[name]) 

2487 

2488 

2489def flatten_structured_array(a): 

2490 """ 

2491 Flatten a structured array. 

2492 

2493 The data type of the output is chosen such that it can represent all of the 

2494 (nested) fields. 

2495 

2496 Parameters 

2497 ---------- 

2498 a : structured array 

2499 

2500 Returns 

2501 ------- 

2502 output : masked array or ndarray 

2503 A flattened masked array if the input is a masked array, otherwise a 

2504 standard ndarray. 

2505 

2506 Examples 

2507 -------- 

2508 >>> ndtype = [('a', int), ('b', float)] 

2509 >>> a = np.array([(1, 1), (2, 2)], dtype=ndtype) 

2510 >>> np.ma.flatten_structured_array(a) 

2511 array([[1., 1.], 

2512 [2., 2.]]) 

2513 

2514 """ 

2515 

2516 def flatten_sequence(iterable): 

2517 """ 

2518 Flattens a compound of nested iterables. 

2519 

2520 """ 

2521 for elm in iter(iterable): 

2522 if hasattr(elm, '__iter__'): 

2523 yield from flatten_sequence(elm) 

2524 else: 

2525 yield elm 

2526 

2527 a = np.asanyarray(a) 

2528 inishape = a.shape 

2529 a = a.ravel() 

2530 if isinstance(a, MaskedArray): 

2531 out = np.array([tuple(flatten_sequence(d.item())) for d in a._data]) 

2532 out = out.view(MaskedArray) 

2533 out._mask = np.array([tuple(flatten_sequence(d.item())) 

2534 for d in getmaskarray(a)]) 

2535 else: 

2536 out = np.array([tuple(flatten_sequence(d.item())) for d in a]) 

2537 if len(inishape) > 1: 

2538 newshape = list(out.shape) 

2539 newshape[0] = inishape 

2540 out.shape = tuple(flatten_sequence(newshape)) 

2541 return out 

2542 

2543 

2544def _arraymethod(funcname, onmask=True): 

2545 """ 

2546 Return a class method wrapper around a basic array method. 

2547 

2548 Creates a class method which returns a masked array, where the new 

2549 ``_data`` array is the output of the corresponding basic method called 

2550 on the original ``_data``. 

2551 

2552 If `onmask` is True, the new mask is the output of the method called 

2553 on the initial mask. Otherwise, the new mask is just a reference 

2554 to the initial mask. 

2555 

2556 Parameters 

2557 ---------- 

2558 funcname : str 

2559 Name of the function to apply on data. 

2560 onmask : bool 

2561 Whether the mask must be processed also (True) or left 

2562 alone (False). Default is True. Make available as `_onmask` 

2563 attribute. 

2564 

2565 Returns 

2566 ------- 

2567 method : instancemethod 

2568 Class method wrapper of the specified basic array method. 

2569 

2570 """ 

2571 def wrapped_method(self, *args, **params): 

2572 result = getattr(self._data, funcname)(*args, **params) 

2573 result = result.view(type(self)) 

2574 result._update_from(self) 

2575 mask = self._mask 

2576 if not onmask: 

2577 result.__setmask__(mask) 

2578 elif mask is not nomask: 

2579 # __setmask__ makes a copy, which we don't want 

2580 result._mask = getattr(mask, funcname)(*args, **params) 

2581 return result 

2582 methdoc = getattr(ndarray, funcname, None) or getattr(np, funcname, None) 

2583 if methdoc is not None: 

2584 wrapped_method.__doc__ = methdoc.__doc__ 

2585 wrapped_method.__name__ = funcname 

2586 return wrapped_method 

2587 

2588 

2589class MaskedIterator: 

2590 """ 

2591 Flat iterator object to iterate over masked arrays. 

2592 

2593 A `MaskedIterator` iterator is returned by ``x.flat`` for any masked array 

2594 `x`. It allows iterating over the array as if it were a 1-D array, 

2595 either in a for-loop or by calling its `next` method. 

2596 

2597 Iteration is done in C-contiguous style, with the last index varying the 

2598 fastest. The iterator can also be indexed using basic slicing or 

2599 advanced indexing. 

2600 

2601 See Also 

2602 -------- 

2603 MaskedArray.flat : Return a flat iterator over an array. 

2604 MaskedArray.flatten : Returns a flattened copy of an array. 

2605 

2606 Notes 

2607 ----- 

2608 `MaskedIterator` is not exported by the `ma` module. Instead of 

2609 instantiating a `MaskedIterator` directly, use `MaskedArray.flat`. 

2610 

2611 Examples 

2612 -------- 

2613 >>> x = np.ma.array(arange(6).reshape(2, 3)) 

2614 >>> fl = x.flat 

2615 >>> type(fl) 

2616 <class 'numpy.ma.core.MaskedIterator'> 

2617 >>> for item in fl: 

2618 ... print(item) 

2619 ... 

2620 0 

2621 1 

2622 2 

2623 3 

2624 4 

2625 5 

2626 

2627 Extracting more than a single element b indexing the `MaskedIterator` 

2628 returns a masked array: 

2629 

2630 >>> fl[2:4] 

2631 masked_array(data = [2 3], 

2632 mask = False, 

2633 fill_value = 999999) 

2634 

2635 """ 

2636 

2637 def __init__(self, ma): 

2638 self.ma = ma 

2639 self.dataiter = ma._data.flat 

2640 

2641 if ma._mask is nomask: 

2642 self.maskiter = None 

2643 else: 

2644 self.maskiter = ma._mask.flat 

2645 

2646 def __iter__(self): 

2647 return self 

2648 

2649 def __getitem__(self, indx): 

2650 result = self.dataiter.__getitem__(indx).view(type(self.ma)) 

2651 if self.maskiter is not None: 

2652 _mask = self.maskiter.__getitem__(indx) 

2653 if isinstance(_mask, ndarray): 

2654 # set shape to match that of data; this is needed for matrices 

2655 _mask.shape = result.shape 

2656 result._mask = _mask 

2657 elif isinstance(_mask, np.void): 

2658 return mvoid(result, mask=_mask, hardmask=self.ma._hardmask) 

2659 elif _mask: # Just a scalar, masked 

2660 return masked 

2661 return result 

2662 

2663 # This won't work if ravel makes a copy 

2664 def __setitem__(self, index, value): 

2665 self.dataiter[index] = getdata(value) 

2666 if self.maskiter is not None: 

2667 self.maskiter[index] = getmaskarray(value) 

2668 

2669 def __next__(self): 

2670 """ 

2671 Return the next value, or raise StopIteration. 

2672 

2673 Examples 

2674 -------- 

2675 >>> x = np.ma.array([3, 2], mask=[0, 1]) 

2676 >>> fl = x.flat 

2677 >>> next(fl) 

2678 3 

2679 >>> next(fl) 

2680 masked 

2681 >>> next(fl) 

2682 Traceback (most recent call last): 

2683 ... 

2684 StopIteration 

2685 

2686 """ 

2687 d = next(self.dataiter) 

2688 if self.maskiter is not None: 

2689 m = next(self.maskiter) 

2690 if isinstance(m, np.void): 

2691 return mvoid(d, mask=m, hardmask=self.ma._hardmask) 

2692 elif m: # Just a scalar, masked 

2693 return masked 

2694 return d 

2695 

2696 

2697class MaskedArray(ndarray): 

2698 """ 

2699 An array class with possibly masked values. 

2700 

2701 Masked values of True exclude the corresponding element from any 

2702 computation. 

2703 

2704 Construction:: 

2705 

2706 x = MaskedArray(data, mask=nomask, dtype=None, copy=False, subok=True, 

2707 ndmin=0, fill_value=None, keep_mask=True, hard_mask=None, 

2708 shrink=True, order=None) 

2709 

2710 Parameters 

2711 ---------- 

2712 data : array_like 

2713 Input data. 

2714 mask : sequence, optional 

2715 Mask. Must be convertible to an array of booleans with the same 

2716 shape as `data`. True indicates a masked (i.e. invalid) data. 

2717 dtype : dtype, optional 

2718 Data type of the output. 

2719 If `dtype` is None, the type of the data argument (``data.dtype``) 

2720 is used. If `dtype` is not None and different from ``data.dtype``, 

2721 a copy is performed. 

2722 copy : bool, optional 

2723 Whether to copy the input data (True), or to use a reference instead. 

2724 Default is False. 

2725 subok : bool, optional 

2726 Whether to return a subclass of `MaskedArray` if possible (True) or a 

2727 plain `MaskedArray`. Default is True. 

2728 ndmin : int, optional 

2729 Minimum number of dimensions. Default is 0. 

2730 fill_value : scalar, optional 

2731 Value used to fill in the masked values when necessary. 

2732 If None, a default based on the data-type is used. 

2733 keep_mask : bool, optional 

2734 Whether to combine `mask` with the mask of the input data, if any 

2735 (True), or to use only `mask` for the output (False). Default is True. 

2736 hard_mask : bool, optional 

2737 Whether to use a hard mask or not. With a hard mask, masked values 

2738 cannot be unmasked. Default is False. 

2739 shrink : bool, optional 

2740 Whether to force compression of an empty mask. Default is True. 

2741 order : {'C', 'F', 'A'}, optional 

2742 Specify the order of the array. If order is 'C', then the array 

2743 will be in C-contiguous order (last-index varies the fastest). 

2744 If order is 'F', then the returned array will be in 

2745 Fortran-contiguous order (first-index varies the fastest). 

2746 If order is 'A' (default), then the returned array may be 

2747 in any order (either C-, Fortran-contiguous, or even discontiguous), 

2748 unless a copy is required, in which case it will be C-contiguous. 

2749 

2750 Examples 

2751 -------- 

2752 

2753 The ``mask`` can be initialized with an array of boolean values 

2754 with the same shape as ``data``. 

2755 

2756 >>> data = np.arange(6).reshape((2, 3)) 

2757 >>> np.ma.MaskedArray(data, mask=[[False, True, False], 

2758 ... [False, False, True]]) 

2759 masked_array( 

2760 data=[[0, --, 2], 

2761 [3, 4, --]], 

2762 mask=[[False, True, False], 

2763 [False, False, True]], 

2764 fill_value=999999) 

2765 

2766 Alternatively, the ``mask`` can be initialized to homogeneous boolean 

2767 array with the same shape as ``data`` by passing in a scalar 

2768 boolean value: 

2769 

2770 >>> np.ma.MaskedArray(data, mask=False) 

2771 masked_array( 

2772 data=[[0, 1, 2], 

2773 [3, 4, 5]], 

2774 mask=[[False, False, False], 

2775 [False, False, False]], 

2776 fill_value=999999) 

2777 

2778 >>> np.ma.MaskedArray(data, mask=True) 

2779 masked_array( 

2780 data=[[--, --, --], 

2781 [--, --, --]], 

2782 mask=[[ True, True, True], 

2783 [ True, True, True]], 

2784 fill_value=999999, 

2785 dtype=int64) 

2786 

2787 .. note:: 

2788 The recommended practice for initializing ``mask`` with a scalar 

2789 boolean value is to use ``True``/``False`` rather than 

2790 ``np.True_``/``np.False_``. The reason is :attr:`nomask` 

2791 is represented internally as ``np.False_``. 

2792 

2793 >>> np.False_ is np.ma.nomask 

2794 True 

2795 

2796 """ 

2797 

2798 __array_priority__ = 15 

2799 _defaultmask = nomask 

2800 _defaulthardmask = False 

2801 _baseclass = ndarray 

2802 

2803 # Maximum number of elements per axis used when printing an array. The 

2804 # 1d case is handled separately because we need more values in this case. 

2805 _print_width = 100 

2806 _print_width_1d = 1500 

2807 

2808 def __new__(cls, data=None, mask=nomask, dtype=None, copy=False, 

2809 subok=True, ndmin=0, fill_value=None, keep_mask=True, 

2810 hard_mask=None, shrink=True, order=None): 

2811 """ 

2812 Create a new masked array from scratch. 

2813 

2814 Notes 

2815 ----- 

2816 A masked array can also be created by taking a .view(MaskedArray). 

2817 

2818 """ 

2819 # Process data. 

2820 _data = np.array(data, dtype=dtype, copy=copy, 

2821 order=order, subok=True, ndmin=ndmin) 

2822 _baseclass = getattr(data, '_baseclass', type(_data)) 

2823 # Check that we're not erasing the mask. 

2824 if isinstance(data, MaskedArray) and (data.shape != _data.shape): 

2825 copy = True 

2826 

2827 # Here, we copy the _view_, so that we can attach new properties to it 

2828 # we must never do .view(MaskedConstant), as that would create a new 

2829 # instance of np.ma.masked, which make identity comparison fail 

2830 if isinstance(data, cls) and subok and not isinstance(data, MaskedConstant): 

2831 _data = ndarray.view(_data, type(data)) 

2832 else: 

2833 _data = ndarray.view(_data, cls) 

2834 

2835 # Handle the case where data is not a subclass of ndarray, but 

2836 # still has the _mask attribute like MaskedArrays 

2837 if hasattr(data, '_mask') and not isinstance(data, ndarray): 

2838 _data._mask = data._mask 

2839 # FIXME: should we set `_data._sharedmask = True`? 

2840 # Process mask. 

2841 # Type of the mask 

2842 mdtype = make_mask_descr(_data.dtype) 

2843 if mask is nomask: 

2844 # Case 1. : no mask in input. 

2845 # Erase the current mask ? 

2846 if not keep_mask: 

2847 # With a reduced version 

2848 if shrink: 

2849 _data._mask = nomask 

2850 # With full version 

2851 else: 

2852 _data._mask = np.zeros(_data.shape, dtype=mdtype) 

2853 # Check whether we missed something 

2854 elif isinstance(data, (tuple, list)): 

2855 try: 

2856 # If data is a sequence of masked array 

2857 mask = np.array( 

2858 [getmaskarray(np.asanyarray(m, dtype=_data.dtype)) 

2859 for m in data], dtype=mdtype) 

2860 except (ValueError, TypeError): 

2861 # If data is nested 

2862 mask = nomask 

2863 # Force shrinking of the mask if needed (and possible) 

2864 if (mdtype == MaskType) and mask.any(): 

2865 _data._mask = mask 

2866 _data._sharedmask = False 

2867 else: 

2868 _data._sharedmask = not copy 

2869 if copy: 

2870 _data._mask = _data._mask.copy() 

2871 # Reset the shape of the original mask 

2872 if getmask(data) is not nomask: 

2873 # gh-21022 encounters an issue here 

2874 # because data._mask.shape is not writeable, but 

2875 # the op was also pointless in that case, because 

2876 # the shapes were the same, so we can at least 

2877 # avoid that path 

2878 if data._mask.shape != data.shape: 

2879 data._mask.shape = data.shape 

2880 else: 

2881 # Case 2. : With a mask in input. 

2882 # If mask is boolean, create an array of True or False 

2883 

2884 # if users pass `mask=None` be forgiving here and cast it False 

2885 # for speed; although the default is `mask=nomask` and can differ. 

2886 if mask is None: 

2887 mask = False 

2888 

2889 if mask is True and mdtype == MaskType: 

2890 mask = np.ones(_data.shape, dtype=mdtype) 

2891 elif mask is False and mdtype == MaskType: 

2892 mask = np.zeros(_data.shape, dtype=mdtype) 

2893 else: 

2894 # Read the mask with the current mdtype 

2895 try: 

2896 mask = np.array(mask, copy=copy, dtype=mdtype) 

2897 # Or assume it's a sequence of bool/int 

2898 except TypeError: 

2899 mask = np.array([tuple([m] * len(mdtype)) for m in mask], 

2900 dtype=mdtype) 

2901 # Make sure the mask and the data have the same shape 

2902 if mask.shape != _data.shape: 

2903 (nd, nm) = (_data.size, mask.size) 

2904 if nm == 1: 

2905 mask = np.resize(mask, _data.shape) 

2906 elif nm == nd: 

2907 mask = np.reshape(mask, _data.shape) 

2908 else: 

2909 msg = "Mask and data not compatible: data size is %i, " + \ 

2910 "mask size is %i." 

2911 raise MaskError(msg % (nd, nm)) 

2912 copy = True 

2913 # Set the mask to the new value 

2914 if _data._mask is nomask: 

2915 _data._mask = mask 

2916 _data._sharedmask = not copy 

2917 else: 

2918 if not keep_mask: 

2919 _data._mask = mask 

2920 _data._sharedmask = not copy 

2921 else: 

2922 if _data.dtype.names is not None: 

2923 def _recursive_or(a, b): 

2924 "do a|=b on each field of a, recursively" 

2925 for name in a.dtype.names: 

2926 (af, bf) = (a[name], b[name]) 

2927 if af.dtype.names is not None: 

2928 _recursive_or(af, bf) 

2929 else: 

2930 af |= bf 

2931 

2932 _recursive_or(_data._mask, mask) 

2933 else: 

2934 _data._mask = np.logical_or(mask, _data._mask) 

2935 _data._sharedmask = False 

2936 

2937 # Update fill_value. 

2938 if fill_value is None: 

2939 fill_value = getattr(data, '_fill_value', None) 

2940 # But don't run the check unless we have something to check. 

2941 if fill_value is not None: 

2942 _data._fill_value = _check_fill_value(fill_value, _data.dtype) 

2943 # Process extra options .. 

2944 if hard_mask is None: 

2945 _data._hardmask = getattr(data, '_hardmask', False) 

2946 else: 

2947 _data._hardmask = hard_mask 

2948 _data._baseclass = _baseclass 

2949 return _data 

2950 

2951 

2952 def _update_from(self, obj): 

2953 """ 

2954 Copies some attributes of obj to self. 

2955 

2956 """ 

2957 if isinstance(obj, ndarray): 

2958 _baseclass = type(obj) 

2959 else: 

2960 _baseclass = ndarray 

2961 # We need to copy the _basedict to avoid backward propagation 

2962 _optinfo = {} 

2963 _optinfo.update(getattr(obj, '_optinfo', {})) 

2964 _optinfo.update(getattr(obj, '_basedict', {})) 

2965 if not isinstance(obj, MaskedArray): 

2966 _optinfo.update(getattr(obj, '__dict__', {})) 

2967 _dict = dict(_fill_value=getattr(obj, '_fill_value', None), 

2968 _hardmask=getattr(obj, '_hardmask', False), 

2969 _sharedmask=getattr(obj, '_sharedmask', False), 

2970 _isfield=getattr(obj, '_isfield', False), 

2971 _baseclass=getattr(obj, '_baseclass', _baseclass), 

2972 _optinfo=_optinfo, 

2973 _basedict=_optinfo) 

2974 self.__dict__.update(_dict) 

2975 self.__dict__.update(_optinfo) 

2976 return 

2977 

2978 def __array_finalize__(self, obj): 

2979 """ 

2980 Finalizes the masked array. 

2981 

2982 """ 

2983 # Get main attributes. 

2984 self._update_from(obj) 

2985 

2986 # We have to decide how to initialize self.mask, based on 

2987 # obj.mask. This is very difficult. There might be some 

2988 # correspondence between the elements in the array we are being 

2989 # created from (= obj) and us. Or there might not. This method can 

2990 # be called in all kinds of places for all kinds of reasons -- could 

2991 # be empty_like, could be slicing, could be a ufunc, could be a view. 

2992 # The numpy subclassing interface simply doesn't give us any way 

2993 # to know, which means that at best this method will be based on 

2994 # guesswork and heuristics. To make things worse, there isn't even any 

2995 # clear consensus about what the desired behavior is. For instance, 

2996 # most users think that np.empty_like(marr) -- which goes via this 

2997 # method -- should return a masked array with an empty mask (see 

2998 # gh-3404 and linked discussions), but others disagree, and they have 

2999 # existing code which depends on empty_like returning an array that 

3000 # matches the input mask. 

3001 # 

3002 # Historically our algorithm was: if the template object mask had the 

3003 # same *number of elements* as us, then we used *it's mask object 

3004 # itself* as our mask, so that writes to us would also write to the 

3005 # original array. This is horribly broken in multiple ways. 

3006 # 

3007 # Now what we do instead is, if the template object mask has the same 

3008 # number of elements as us, and we do not have the same base pointer 

3009 # as the template object (b/c views like arr[...] should keep the same 

3010 # mask), then we make a copy of the template object mask and use 

3011 # that. This is also horribly broken but somewhat less so. Maybe. 

3012 if isinstance(obj, ndarray): 

3013 # XX: This looks like a bug -- shouldn't it check self.dtype 

3014 # instead? 

3015 if obj.dtype.names is not None: 

3016 _mask = getmaskarray(obj) 

3017 else: 

3018 _mask = getmask(obj) 

3019 

3020 # If self and obj point to exactly the same data, then probably 

3021 # self is a simple view of obj (e.g., self = obj[...]), so they 

3022 # should share the same mask. (This isn't 100% reliable, e.g. self 

3023 # could be the first row of obj, or have strange strides, but as a 

3024 # heuristic it's not bad.) In all other cases, we make a copy of 

3025 # the mask, so that future modifications to 'self' do not end up 

3026 # side-effecting 'obj' as well. 

3027 if (_mask is not nomask and obj.__array_interface__["data"][0] 

3028 != self.__array_interface__["data"][0]): 

3029 # We should make a copy. But we could get here via astype, 

3030 # in which case the mask might need a new dtype as well 

3031 # (e.g., changing to or from a structured dtype), and the 

3032 # order could have changed. So, change the mask type if 

3033 # needed and use astype instead of copy. 

3034 if self.dtype == obj.dtype: 

3035 _mask_dtype = _mask.dtype 

3036 else: 

3037 _mask_dtype = make_mask_descr(self.dtype) 

3038 

3039 if self.flags.c_contiguous: 

3040 order = "C" 

3041 elif self.flags.f_contiguous: 

3042 order = "F" 

3043 else: 

3044 order = "K" 

3045 

3046 _mask = _mask.astype(_mask_dtype, order) 

3047 else: 

3048 # Take a view so shape changes, etc., do not propagate back. 

3049 _mask = _mask.view() 

3050 else: 

3051 _mask = nomask 

3052 

3053 self._mask = _mask 

3054 # Finalize the mask 

3055 if self._mask is not nomask: 

3056 try: 

3057 self._mask.shape = self.shape 

3058 except ValueError: 

3059 self._mask = nomask 

3060 except (TypeError, AttributeError): 

3061 # When _mask.shape is not writable (because it's a void) 

3062 pass 

3063 

3064 # Finalize the fill_value 

3065 if self._fill_value is not None: 

3066 self._fill_value = _check_fill_value(self._fill_value, self.dtype) 

3067 elif self.dtype.names is not None: 

3068 # Finalize the default fill_value for structured arrays 

3069 self._fill_value = _check_fill_value(None, self.dtype) 

3070 

3071 def __array_wrap__(self, obj, context=None): 

3072 """ 

3073 Special hook for ufuncs. 

3074 

3075 Wraps the numpy array and sets the mask according to context. 

3076 

3077 """ 

3078 if obj is self: # for in-place operations 

3079 result = obj 

3080 else: 

3081 result = obj.view(type(self)) 

3082 result._update_from(self) 

3083 

3084 if context is not None: 

3085 result._mask = result._mask.copy() 

3086 func, args, out_i = context 

3087 # args sometimes contains outputs (gh-10459), which we don't want 

3088 input_args = args[:func.nin] 

3089 m = reduce(mask_or, [getmaskarray(arg) for arg in input_args]) 

3090 # Get the domain mask 

3091 domain = ufunc_domain.get(func, None) 

3092 if domain is not None: 

3093 # Take the domain, and make sure it's a ndarray 

3094 with np.errstate(divide='ignore', invalid='ignore'): 

3095 d = filled(domain(*input_args), True) 

3096 

3097 if d.any(): 

3098 # Fill the result where the domain is wrong 

3099 try: 

3100 # Binary domain: take the last value 

3101 fill_value = ufunc_fills[func][-1] 

3102 except TypeError: 

3103 # Unary domain: just use this one 

3104 fill_value = ufunc_fills[func] 

3105 except KeyError: 

3106 # Domain not recognized, use fill_value instead 

3107 fill_value = self.fill_value 

3108 

3109 np.copyto(result, fill_value, where=d) 

3110 

3111 # Update the mask 

3112 if m is nomask: 

3113 m = d 

3114 else: 

3115 # Don't modify inplace, we risk back-propagation 

3116 m = (m | d) 

3117 

3118 # Make sure the mask has the proper size 

3119 if result is not self and result.shape == () and m: 

3120 return masked 

3121 else: 

3122 result._mask = m 

3123 result._sharedmask = False 

3124 

3125 return result 

3126 

3127 def view(self, dtype=None, type=None, fill_value=None): 

3128 """ 

3129 Return a view of the MaskedArray data. 

3130 

3131 Parameters 

3132 ---------- 

3133 dtype : data-type or ndarray sub-class, optional 

3134 Data-type descriptor of the returned view, e.g., float32 or int16. 

3135 The default, None, results in the view having the same data-type 

3136 as `a`. As with ``ndarray.view``, dtype can also be specified as 

3137 an ndarray sub-class, which then specifies the type of the 

3138 returned object (this is equivalent to setting the ``type`` 

3139 parameter). 

3140 type : Python type, optional 

3141 Type of the returned view, either ndarray or a subclass. The 

3142 default None results in type preservation. 

3143 fill_value : scalar, optional 

3144 The value to use for invalid entries (None by default). 

3145 If None, then this argument is inferred from the passed `dtype`, or 

3146 in its absence the original array, as discussed in the notes below. 

3147 

3148 See Also 

3149 -------- 

3150 numpy.ndarray.view : Equivalent method on ndarray object. 

3151 

3152 Notes 

3153 ----- 

3154 

3155 ``a.view()`` is used two different ways: 

3156 

3157 ``a.view(some_dtype)`` or ``a.view(dtype=some_dtype)`` constructs a view 

3158 of the array's memory with a different data-type. This can cause a 

3159 reinterpretation of the bytes of memory. 

3160 

3161 ``a.view(ndarray_subclass)`` or ``a.view(type=ndarray_subclass)`` just 

3162 returns an instance of `ndarray_subclass` that looks at the same array 

3163 (same shape, dtype, etc.) This does not cause a reinterpretation of the 

3164 memory. 

3165 

3166 If `fill_value` is not specified, but `dtype` is specified (and is not 

3167 an ndarray sub-class), the `fill_value` of the MaskedArray will be 

3168 reset. If neither `fill_value` nor `dtype` are specified (or if 

3169 `dtype` is an ndarray sub-class), then the fill value is preserved. 

3170 Finally, if `fill_value` is specified, but `dtype` is not, the fill 

3171 value is set to the specified value. 

3172 

3173 For ``a.view(some_dtype)``, if ``some_dtype`` has a different number of 

3174 bytes per entry than the previous dtype (for example, converting a 

3175 regular array to a structured array), then the behavior of the view 

3176 cannot be predicted just from the superficial appearance of ``a`` (shown 

3177 by ``print(a)``). It also depends on exactly how ``a`` is stored in 

3178 memory. Therefore if ``a`` is C-ordered versus fortran-ordered, versus 

3179 defined as a slice or transpose, etc., the view may give different 

3180 results. 

3181 """ 

3182 

3183 if dtype is None: 

3184 if type is None: 

3185 output = ndarray.view(self) 

3186 else: 

3187 output = ndarray.view(self, type) 

3188 elif type is None: 

3189 try: 

3190 if issubclass(dtype, ndarray): 

3191 output = ndarray.view(self, dtype) 

3192 dtype = None 

3193 else: 

3194 output = ndarray.view(self, dtype) 

3195 except TypeError: 

3196 output = ndarray.view(self, dtype) 

3197 else: 

3198 output = ndarray.view(self, dtype, type) 

3199 

3200 # also make the mask be a view (so attr changes to the view's 

3201 # mask do no affect original object's mask) 

3202 # (especially important to avoid affecting np.masked singleton) 

3203 if getmask(output) is not nomask: 

3204 output._mask = output._mask.view() 

3205 

3206 # Make sure to reset the _fill_value if needed 

3207 if getattr(output, '_fill_value', None) is not None: 

3208 if fill_value is None: 

3209 if dtype is None: 

3210 pass # leave _fill_value as is 

3211 else: 

3212 output._fill_value = None 

3213 else: 

3214 output.fill_value = fill_value 

3215 return output 

3216 

3217 def __getitem__(self, indx): 

3218 """ 

3219 x.__getitem__(y) <==> x[y] 

3220 

3221 Return the item described by i, as a masked array. 

3222 

3223 """ 

3224 # We could directly use ndarray.__getitem__ on self. 

3225 # But then we would have to modify __array_finalize__ to prevent the 

3226 # mask of being reshaped if it hasn't been set up properly yet 

3227 # So it's easier to stick to the current version 

3228 dout = self.data[indx] 

3229 _mask = self._mask 

3230 

3231 def _is_scalar(m): 

3232 return not isinstance(m, np.ndarray) 

3233 

3234 def _scalar_heuristic(arr, elem): 

3235 """ 

3236 Return whether `elem` is a scalar result of indexing `arr`, or None 

3237 if undecidable without promoting nomask to a full mask 

3238 """ 

3239 # obviously a scalar 

3240 if not isinstance(elem, np.ndarray): 

3241 return True 

3242 

3243 # object array scalar indexing can return anything 

3244 elif arr.dtype.type is np.object_: 

3245 if arr.dtype is not elem.dtype: 

3246 # elem is an array, but dtypes do not match, so must be 

3247 # an element 

3248 return True 

3249 

3250 # well-behaved subclass that only returns 0d arrays when 

3251 # expected - this is not a scalar 

3252 elif type(arr).__getitem__ == ndarray.__getitem__: 

3253 return False 

3254 

3255 return None 

3256 

3257 if _mask is not nomask: 

3258 # _mask cannot be a subclass, so it tells us whether we should 

3259 # expect a scalar. It also cannot be of dtype object. 

3260 mout = _mask[indx] 

3261 scalar_expected = _is_scalar(mout) 

3262 

3263 else: 

3264 # attempt to apply the heuristic to avoid constructing a full mask 

3265 mout = nomask 

3266 scalar_expected = _scalar_heuristic(self.data, dout) 

3267 if scalar_expected is None: 

3268 # heuristics have failed 

3269 # construct a full array, so we can be certain. This is costly. 

3270 # we could also fall back on ndarray.__getitem__(self.data, indx) 

3271 scalar_expected = _is_scalar(getmaskarray(self)[indx]) 

3272 

3273 # Did we extract a single item? 

3274 if scalar_expected: 

3275 # A record 

3276 if isinstance(dout, np.void): 

3277 # We should always re-cast to mvoid, otherwise users can 

3278 # change masks on rows that already have masked values, but not 

3279 # on rows that have no masked values, which is inconsistent. 

3280 return mvoid(dout, mask=mout, hardmask=self._hardmask) 

3281 

3282 # special case introduced in gh-5962 

3283 elif (self.dtype.type is np.object_ and 

3284 isinstance(dout, np.ndarray) and 

3285 dout is not masked): 

3286 # If masked, turn into a MaskedArray, with everything masked. 

3287 if mout: 

3288 return MaskedArray(dout, mask=True) 

3289 else: 

3290 return dout 

3291 

3292 # Just a scalar 

3293 else: 

3294 if mout: 

3295 return masked 

3296 else: 

3297 return dout 

3298 else: 

3299 # Force dout to MA 

3300 dout = dout.view(type(self)) 

3301 # Inherit attributes from self 

3302 dout._update_from(self) 

3303 # Check the fill_value 

3304 if is_string_or_list_of_strings(indx): 

3305 if self._fill_value is not None: 

3306 dout._fill_value = self._fill_value[indx] 

3307 

3308 # Something like gh-15895 has happened if this check fails. 

3309 # _fill_value should always be an ndarray. 

3310 if not isinstance(dout._fill_value, np.ndarray): 

3311 raise RuntimeError('Internal NumPy error.') 

3312 # If we're indexing a multidimensional field in a 

3313 # structured array (such as dtype("(2,)i2,(2,)i1")), 

3314 # dimensionality goes up (M[field].ndim == M.ndim + 

3315 # M.dtype[field].ndim). That's fine for 

3316 # M[field] but problematic for M[field].fill_value 

3317 # which should have shape () to avoid breaking several 

3318 # methods. There is no great way out, so set to 

3319 # first element. See issue #6723. 

3320 if dout._fill_value.ndim > 0: 

3321 if not (dout._fill_value == 

3322 dout._fill_value.flat[0]).all(): 

3323 warnings.warn( 

3324 "Upon accessing multidimensional field " 

3325 f"{indx!s}, need to keep dimensionality " 

3326 "of fill_value at 0. Discarding " 

3327 "heterogeneous fill_value and setting " 

3328 f"all to {dout._fill_value[0]!s}.", 

3329 stacklevel=2) 

3330 # Need to use `.flat[0:1].squeeze(...)` instead of just 

3331 # `.flat[0]` to ensure the result is a 0d array and not 

3332 # a scalar. 

3333 dout._fill_value = dout._fill_value.flat[0:1].squeeze(axis=0) 

3334 dout._isfield = True 

3335 # Update the mask if needed 

3336 if mout is not nomask: 

3337 # set shape to match that of data; this is needed for matrices 

3338 dout._mask = reshape(mout, dout.shape) 

3339 dout._sharedmask = True 

3340 # Note: Don't try to check for m.any(), that'll take too long 

3341 return dout 

3342 

3343 # setitem may put NaNs into integer arrays or occasionally overflow a 

3344 # float. But this may happen in masked values, so avoid otherwise 

3345 # correct warnings (as is typical also in masked calculations). 

3346 @np.errstate(over='ignore', invalid='ignore') 

3347 def __setitem__(self, indx, value): 

3348 """ 

3349 x.__setitem__(i, y) <==> x[i]=y 

3350 

3351 Set item described by index. If value is masked, masks those 

3352 locations. 

3353 

3354 """ 

3355 if self is masked: 

3356 raise MaskError('Cannot alter the masked element.') 

3357 _data = self._data 

3358 _mask = self._mask 

3359 if isinstance(indx, str): 

3360 _data[indx] = value 

3361 if _mask is nomask: 

3362 self._mask = _mask = make_mask_none(self.shape, self.dtype) 

3363 _mask[indx] = getmask(value) 

3364 return 

3365 

3366 _dtype = _data.dtype 

3367 

3368 if value is masked: 

3369 # The mask wasn't set: create a full version. 

3370 if _mask is nomask: 

3371 _mask = self._mask = make_mask_none(self.shape, _dtype) 

3372 # Now, set the mask to its value. 

3373 if _dtype.names is not None: 

3374 _mask[indx] = tuple([True] * len(_dtype.names)) 

3375 else: 

3376 _mask[indx] = True 

3377 return 

3378 

3379 # Get the _data part of the new value 

3380 dval = getattr(value, '_data', value) 

3381 # Get the _mask part of the new value 

3382 mval = getmask(value) 

3383 if _dtype.names is not None and mval is nomask: 

3384 mval = tuple([False] * len(_dtype.names)) 

3385 if _mask is nomask: 

3386 # Set the data, then the mask 

3387 _data[indx] = dval 

3388 if mval is not nomask: 

3389 _mask = self._mask = make_mask_none(self.shape, _dtype) 

3390 _mask[indx] = mval 

3391 elif not self._hardmask: 

3392 # Set the data, then the mask 

3393 if (isinstance(indx, masked_array) and 

3394 not isinstance(value, masked_array)): 

3395 _data[indx.data] = dval 

3396 else: 

3397 _data[indx] = dval 

3398 _mask[indx] = mval 

3399 elif hasattr(indx, 'dtype') and (indx.dtype == MaskType): 

3400 indx = indx * umath.logical_not(_mask) 

3401 _data[indx] = dval 

3402 else: 

3403 if _dtype.names is not None: 

3404 err_msg = "Flexible 'hard' masks are not yet supported." 

3405 raise NotImplementedError(err_msg) 

3406 mindx = mask_or(_mask[indx], mval, copy=True) 

3407 dindx = self._data[indx] 

3408 if dindx.size > 1: 

3409 np.copyto(dindx, dval, where=~mindx) 

3410 elif mindx is nomask: 

3411 dindx = dval 

3412 _data[indx] = dindx 

3413 _mask[indx] = mindx 

3414 return 

3415 

3416 # Define so that we can overwrite the setter. 

3417 @property 

3418 def dtype(self): 

3419 return super().dtype 

3420 

3421 @dtype.setter 

3422 def dtype(self, dtype): 

3423 super(MaskedArray, type(self)).dtype.__set__(self, dtype) 

3424 if self._mask is not nomask: 

3425 self._mask = self._mask.view(make_mask_descr(dtype), ndarray) 

3426 # Try to reset the shape of the mask (if we don't have a void). 

3427 # This raises a ValueError if the dtype change won't work. 

3428 try: 

3429 self._mask.shape = self.shape 

3430 except (AttributeError, TypeError): 

3431 pass 

3432 

3433 @property 

3434 def shape(self): 

3435 return super().shape 

3436 

3437 @shape.setter 

3438 def shape(self, shape): 

3439 super(MaskedArray, type(self)).shape.__set__(self, shape) 

3440 # Cannot use self._mask, since it may not (yet) exist when a 

3441 # masked matrix sets the shape. 

3442 if getmask(self) is not nomask: 

3443 self._mask.shape = self.shape 

3444 

3445 def __setmask__(self, mask, copy=False): 

3446 """ 

3447 Set the mask. 

3448 

3449 """ 

3450 idtype = self.dtype 

3451 current_mask = self._mask 

3452 if mask is masked: 

3453 mask = True 

3454 

3455 if current_mask is nomask: 

3456 # Make sure the mask is set 

3457 # Just don't do anything if there's nothing to do. 

3458 if mask is nomask: 

3459 return 

3460 current_mask = self._mask = make_mask_none(self.shape, idtype) 

3461 

3462 if idtype.names is None: 

3463 # No named fields. 

3464 # Hardmask: don't unmask the data 

3465 if self._hardmask: 

3466 current_mask |= mask 

3467 # Softmask: set everything to False 

3468 # If it's obviously a compatible scalar, use a quick update 

3469 # method. 

3470 elif isinstance(mask, (int, float, np.bool_, np.number)): 

3471 current_mask[...] = mask 

3472 # Otherwise fall back to the slower, general purpose way. 

3473 else: 

3474 current_mask.flat = mask 

3475 else: 

3476 # Named fields w/ 

3477 mdtype = current_mask.dtype 

3478 mask = np.array(mask, copy=False) 

3479 # Mask is a singleton 

3480 if not mask.ndim: 

3481 # It's a boolean : make a record 

3482 if mask.dtype.kind == 'b': 

3483 mask = np.array(tuple([mask.item()] * len(mdtype)), 

3484 dtype=mdtype) 

3485 # It's a record: make sure the dtype is correct 

3486 else: 

3487 mask = mask.astype(mdtype) 

3488 # Mask is a sequence 

3489 else: 

3490 # Make sure the new mask is a ndarray with the proper dtype 

3491 try: 

3492 mask = np.array(mask, copy=copy, dtype=mdtype) 

3493 # Or assume it's a sequence of bool/int 

3494 except TypeError: 

3495 mask = np.array([tuple([m] * len(mdtype)) for m in mask], 

3496 dtype=mdtype) 

3497 # Hardmask: don't unmask the data 

3498 if self._hardmask: 

3499 for n in idtype.names: 

3500 current_mask[n] |= mask[n] 

3501 # Softmask: set everything to False 

3502 # If it's obviously a compatible scalar, use a quick update 

3503 # method. 

3504 elif isinstance(mask, (int, float, np.bool_, np.number)): 

3505 current_mask[...] = mask 

3506 # Otherwise fall back to the slower, general purpose way. 

3507 else: 

3508 current_mask.flat = mask 

3509 # Reshape if needed 

3510 if current_mask.shape: 

3511 current_mask.shape = self.shape 

3512 return 

3513 

3514 _set_mask = __setmask__ 

3515 

3516 @property 

3517 def mask(self): 

3518 """ Current mask. """ 

3519 

3520 # We could try to force a reshape, but that wouldn't work in some 

3521 # cases. 

3522 # Return a view so that the dtype and shape cannot be changed in place 

3523 # This still preserves nomask by identity 

3524 return self._mask.view() 

3525 

3526 @mask.setter 

3527 def mask(self, value): 

3528 self.__setmask__(value) 

3529 

3530 @property 

3531 def recordmask(self): 

3532 """ 

3533 Get or set the mask of the array if it has no named fields. For 

3534 structured arrays, returns a ndarray of booleans where entries are 

3535 ``True`` if **all** the fields are masked, ``False`` otherwise: 

3536 

3537 >>> x = np.ma.array([(1, 1), (2, 2), (3, 3), (4, 4), (5, 5)], 

3538 ... mask=[(0, 0), (1, 0), (1, 1), (0, 1), (0, 0)], 

3539 ... dtype=[('a', int), ('b', int)]) 

3540 >>> x.recordmask 

3541 array([False, False, True, False, False]) 

3542 """ 

3543 

3544 _mask = self._mask.view(ndarray) 

3545 if _mask.dtype.names is None: 

3546 return _mask 

3547 return np.all(flatten_structured_array(_mask), axis=-1) 

3548 

3549 @recordmask.setter 

3550 def recordmask(self, mask): 

3551 raise NotImplementedError("Coming soon: setting the mask per records!") 

3552 

3553 def harden_mask(self): 

3554 """ 

3555 Force the mask to hard, preventing unmasking by assignment. 

3556 

3557 Whether the mask of a masked array is hard or soft is determined by 

3558 its `~ma.MaskedArray.hardmask` property. `harden_mask` sets 

3559 `~ma.MaskedArray.hardmask` to ``True`` (and returns the modified 

3560 self). 

3561 

3562 See Also 

3563 -------- 

3564 ma.MaskedArray.hardmask 

3565 ma.MaskedArray.soften_mask 

3566 

3567 """ 

3568 self._hardmask = True 

3569 return self 

3570 

3571 def soften_mask(self): 

3572 """ 

3573 Force the mask to soft (default), allowing unmasking by assignment. 

3574 

3575 Whether the mask of a masked array is hard or soft is determined by 

3576 its `~ma.MaskedArray.hardmask` property. `soften_mask` sets 

3577 `~ma.MaskedArray.hardmask` to ``False`` (and returns the modified 

3578 self). 

3579 

3580 See Also 

3581 -------- 

3582 ma.MaskedArray.hardmask 

3583 ma.MaskedArray.harden_mask 

3584 

3585 """ 

3586 self._hardmask = False 

3587 return self 

3588 

3589 @property 

3590 def hardmask(self): 

3591 """ 

3592 Specifies whether values can be unmasked through assignments. 

3593 

3594 By default, assigning definite values to masked array entries will 

3595 unmask them. When `hardmask` is ``True``, the mask will not change 

3596 through assignments. 

3597 

3598 See Also 

3599 -------- 

3600 ma.MaskedArray.harden_mask 

3601 ma.MaskedArray.soften_mask 

3602 

3603 Examples 

3604 -------- 

3605 >>> x = np.arange(10) 

3606 >>> m = np.ma.masked_array(x, x>5) 

3607 >>> assert not m.hardmask 

3608 

3609 Since `m` has a soft mask, assigning an element value unmasks that 

3610 element: 

3611 

3612 >>> m[8] = 42 

3613 >>> m 

3614 masked_array(data=[0, 1, 2, 3, 4, 5, --, --, 42, --], 

3615 mask=[False, False, False, False, False, False, 

3616 True, True, False, True], 

3617 fill_value=999999) 

3618 

3619 After hardening, the mask is not affected by assignments: 

3620 

3621 >>> hardened = np.ma.harden_mask(m) 

3622 >>> assert m.hardmask and hardened is m 

3623 >>> m[:] = 23 

3624 >>> m 

3625 masked_array(data=[23, 23, 23, 23, 23, 23, --, --, 23, --], 

3626 mask=[False, False, False, False, False, False, 

3627 True, True, False, True], 

3628 fill_value=999999) 

3629 

3630 """ 

3631 return self._hardmask 

3632 

3633 def unshare_mask(self): 

3634 """ 

3635 Copy the mask and set the `sharedmask` flag to ``False``. 

3636 

3637 Whether the mask is shared between masked arrays can be seen from 

3638 the `sharedmask` property. `unshare_mask` ensures the mask is not 

3639 shared. A copy of the mask is only made if it was shared. 

3640 

3641 See Also 

3642 -------- 

3643 sharedmask 

3644 

3645 """ 

3646 if self._sharedmask: 

3647 self._mask = self._mask.copy() 

3648 self._sharedmask = False 

3649 return self 

3650 

3651 @property 

3652 def sharedmask(self): 

3653 """ Share status of the mask (read-only). """ 

3654 return self._sharedmask 

3655 

3656 def shrink_mask(self): 

3657 """ 

3658 Reduce a mask to nomask when possible. 

3659 

3660 Parameters 

3661 ---------- 

3662 None 

3663 

3664 Returns 

3665 ------- 

3666 None 

3667 

3668 Examples 

3669 -------- 

3670 >>> x = np.ma.array([[1,2 ], [3, 4]], mask=[0]*4) 

3671 >>> x.mask 

3672 array([[False, False], 

3673 [False, False]]) 

3674 >>> x.shrink_mask() 

3675 masked_array( 

3676 data=[[1, 2], 

3677 [3, 4]], 

3678 mask=False, 

3679 fill_value=999999) 

3680 >>> x.mask 

3681 False 

3682 

3683 """ 

3684 self._mask = _shrink_mask(self._mask) 

3685 return self 

3686 

3687 @property 

3688 def baseclass(self): 

3689 """ Class of the underlying data (read-only). """ 

3690 return self._baseclass 

3691 

3692 def _get_data(self): 

3693 """ 

3694 Returns the underlying data, as a view of the masked array. 

3695 

3696 If the underlying data is a subclass of :class:`numpy.ndarray`, it is 

3697 returned as such. 

3698 

3699 >>> x = np.ma.array(np.matrix([[1, 2], [3, 4]]), mask=[[0, 1], [1, 0]]) 

3700 >>> x.data 

3701 matrix([[1, 2], 

3702 [3, 4]]) 

3703 

3704 The type of the data can be accessed through the :attr:`baseclass` 

3705 attribute. 

3706 """ 

3707 return ndarray.view(self, self._baseclass) 

3708 

3709 _data = property(fget=_get_data) 

3710 data = property(fget=_get_data) 

3711 

3712 @property 

3713 def flat(self): 

3714 """ Return a flat iterator, or set a flattened version of self to value. """ 

3715 return MaskedIterator(self) 

3716 

3717 @flat.setter 

3718 def flat(self, value): 

3719 y = self.ravel() 

3720 y[:] = value 

3721 

3722 @property 

3723 def fill_value(self): 

3724 """ 

3725 The filling value of the masked array is a scalar. When setting, None 

3726 will set to a default based on the data type. 

3727 

3728 Examples 

3729 -------- 

3730 >>> for dt in [np.int32, np.int64, np.float64, np.complex128]: 

3731 ... np.ma.array([0, 1], dtype=dt).get_fill_value() 

3732 ... 

3733 999999 

3734 999999 

3735 1e+20 

3736 (1e+20+0j) 

3737 

3738 >>> x = np.ma.array([0, 1.], fill_value=-np.inf) 

3739 >>> x.fill_value 

3740 -inf 

3741 >>> x.fill_value = np.pi 

3742 >>> x.fill_value 

3743 3.1415926535897931 # may vary 

3744 

3745 Reset to default: 

3746 

3747 >>> x.fill_value = None 

3748 >>> x.fill_value 

3749 1e+20 

3750 

3751 """ 

3752 if self._fill_value is None: 

3753 self._fill_value = _check_fill_value(None, self.dtype) 

3754 

3755 # Temporary workaround to account for the fact that str and bytes 

3756 # scalars cannot be indexed with (), whereas all other numpy 

3757 # scalars can. See issues #7259 and #7267. 

3758 # The if-block can be removed after #7267 has been fixed. 

3759 if isinstance(self._fill_value, ndarray): 

3760 return self._fill_value[()] 

3761 return self._fill_value 

3762 

3763 @fill_value.setter 

3764 def fill_value(self, value=None): 

3765 target = _check_fill_value(value, self.dtype) 

3766 if not target.ndim == 0: 

3767 # 2019-11-12, 1.18.0 

3768 warnings.warn( 

3769 "Non-scalar arrays for the fill value are deprecated. Use " 

3770 "arrays with scalar values instead. The filled function " 

3771 "still supports any array as `fill_value`.", 

3772 DeprecationWarning, stacklevel=2) 

3773 

3774 _fill_value = self._fill_value 

3775 if _fill_value is None: 

3776 # Create the attribute if it was undefined 

3777 self._fill_value = target 

3778 else: 

3779 # Don't overwrite the attribute, just fill it (for propagation) 

3780 _fill_value[()] = target 

3781 

3782 # kept for compatibility 

3783 get_fill_value = fill_value.fget 

3784 set_fill_value = fill_value.fset 

3785 

3786 def filled(self, fill_value=None): 

3787 """ 

3788 Return a copy of self, with masked values filled with a given value. 

3789 **However**, if there are no masked values to fill, self will be 

3790 returned instead as an ndarray. 

3791 

3792 Parameters 

3793 ---------- 

3794 fill_value : array_like, optional 

3795 The value to use for invalid entries. Can be scalar or non-scalar. 

3796 If non-scalar, the resulting ndarray must be broadcastable over 

3797 input array. Default is None, in which case, the `fill_value` 

3798 attribute of the array is used instead. 

3799 

3800 Returns 

3801 ------- 

3802 filled_array : ndarray 

3803 A copy of ``self`` with invalid entries replaced by *fill_value* 

3804 (be it the function argument or the attribute of ``self``), or 

3805 ``self`` itself as an ndarray if there are no invalid entries to 

3806 be replaced. 

3807 

3808 Notes 

3809 ----- 

3810 The result is **not** a MaskedArray! 

3811 

3812 Examples 

3813 -------- 

3814 >>> x = np.ma.array([1,2,3,4,5], mask=[0,0,1,0,1], fill_value=-999) 

3815 >>> x.filled() 

3816 array([ 1, 2, -999, 4, -999]) 

3817 >>> x.filled(fill_value=1000) 

3818 array([ 1, 2, 1000, 4, 1000]) 

3819 >>> type(x.filled()) 

3820 <class 'numpy.ndarray'> 

3821 

3822 Subclassing is preserved. This means that if, e.g., the data part of 

3823 the masked array is a recarray, `filled` returns a recarray: 

3824 

3825 >>> x = np.array([(-1, 2), (-3, 4)], dtype='i8,i8').view(np.recarray) 

3826 >>> m = np.ma.array(x, mask=[(True, False), (False, True)]) 

3827 >>> m.filled() 

3828 rec.array([(999999, 2), ( -3, 999999)], 

3829 dtype=[('f0', '<i8'), ('f1', '<i8')]) 

3830 """ 

3831 m = self._mask 

3832 if m is nomask: 

3833 return self._data 

3834 

3835 if fill_value is None: 

3836 fill_value = self.fill_value 

3837 else: 

3838 fill_value = _check_fill_value(fill_value, self.dtype) 

3839 

3840 if self is masked_singleton: 

3841 return np.asanyarray(fill_value) 

3842 

3843 if m.dtype.names is not None: 

3844 result = self._data.copy('K') 

3845 _recursive_filled(result, self._mask, fill_value) 

3846 elif not m.any(): 

3847 return self._data 

3848 else: 

3849 result = self._data.copy('K') 

3850 try: 

3851 np.copyto(result, fill_value, where=m) 

3852 except (TypeError, AttributeError): 

3853 fill_value = narray(fill_value, dtype=object) 

3854 d = result.astype(object) 

3855 result = np.choose(m, (d, fill_value)) 

3856 except IndexError: 

3857 # ok, if scalar 

3858 if self._data.shape: 

3859 raise 

3860 elif m: 

3861 result = np.array(fill_value, dtype=self.dtype) 

3862 else: 

3863 result = self._data 

3864 return result 

3865 

3866 def compressed(self): 

3867 """ 

3868 Return all the non-masked data as a 1-D array. 

3869 

3870 Returns 

3871 ------- 

3872 data : ndarray 

3873 A new `ndarray` holding the non-masked data is returned. 

3874 

3875 Notes 

3876 ----- 

3877 The result is **not** a MaskedArray! 

3878 

3879 Examples 

3880 -------- 

3881 >>> x = np.ma.array(np.arange(5), mask=[0]*2 + [1]*3) 

3882 >>> x.compressed() 

3883 array([0, 1]) 

3884 >>> type(x.compressed()) 

3885 <class 'numpy.ndarray'> 

3886 

3887 """ 

3888 data = ndarray.ravel(self._data) 

3889 if self._mask is not nomask: 

3890 data = data.compress(np.logical_not(ndarray.ravel(self._mask))) 

3891 return data 

3892 

3893 def compress(self, condition, axis=None, out=None): 

3894 """ 

3895 Return `a` where condition is ``True``. 

3896 

3897 If condition is a `~ma.MaskedArray`, missing values are considered 

3898 as ``False``. 

3899 

3900 Parameters 

3901 ---------- 

3902 condition : var 

3903 Boolean 1-d array selecting which entries to return. If len(condition) 

3904 is less than the size of a along the axis, then output is truncated 

3905 to length of condition array. 

3906 axis : {None, int}, optional 

3907 Axis along which the operation must be performed. 

3908 out : {None, ndarray}, optional 

3909 Alternative output array in which to place the result. It must have 

3910 the same shape as the expected output but the type will be cast if 

3911 necessary. 

3912 

3913 Returns 

3914 ------- 

3915 result : MaskedArray 

3916 A :class:`~ma.MaskedArray` object. 

3917 

3918 Notes 

3919 ----- 

3920 Please note the difference with :meth:`compressed` ! 

3921 The output of :meth:`compress` has a mask, the output of 

3922 :meth:`compressed` does not. 

3923 

3924 Examples 

3925 -------- 

3926 >>> x = np.ma.array([[1,2,3],[4,5,6],[7,8,9]], mask=[0] + [1,0]*4) 

3927 >>> x 

3928 masked_array( 

3929 data=[[1, --, 3], 

3930 [--, 5, --], 

3931 [7, --, 9]], 

3932 mask=[[False, True, False], 

3933 [ True, False, True], 

3934 [False, True, False]], 

3935 fill_value=999999) 

3936 >>> x.compress([1, 0, 1]) 

3937 masked_array(data=[1, 3], 

3938 mask=[False, False], 

3939 fill_value=999999) 

3940 

3941 >>> x.compress([1, 0, 1], axis=1) 

3942 masked_array( 

3943 data=[[1, 3], 

3944 [--, --], 

3945 [7, 9]], 

3946 mask=[[False, False], 

3947 [ True, True], 

3948 [False, False]], 

3949 fill_value=999999) 

3950 

3951 """ 

3952 # Get the basic components 

3953 (_data, _mask) = (self._data, self._mask) 

3954 

3955 # Force the condition to a regular ndarray and forget the missing 

3956 # values. 

3957 condition = np.asarray(condition) 

3958 

3959 _new = _data.compress(condition, axis=axis, out=out).view(type(self)) 

3960 _new._update_from(self) 

3961 if _mask is not nomask: 

3962 _new._mask = _mask.compress(condition, axis=axis) 

3963 return _new 

3964 

3965 def _insert_masked_print(self): 

3966 """ 

3967 Replace masked values with masked_print_option, casting all innermost 

3968 dtypes to object. 

3969 """ 

3970 if masked_print_option.enabled(): 

3971 mask = self._mask 

3972 if mask is nomask: 

3973 res = self._data 

3974 else: 

3975 # convert to object array to make filled work 

3976 data = self._data 

3977 # For big arrays, to avoid a costly conversion to the 

3978 # object dtype, extract the corners before the conversion. 

3979 print_width = (self._print_width if self.ndim > 1 

3980 else self._print_width_1d) 

3981 for axis in range(self.ndim): 

3982 if data.shape[axis] > print_width: 

3983 ind = print_width // 2 

3984 arr = np.split(data, (ind, -ind), axis=axis) 

3985 data = np.concatenate((arr[0], arr[2]), axis=axis) 

3986 arr = np.split(mask, (ind, -ind), axis=axis) 

3987 mask = np.concatenate((arr[0], arr[2]), axis=axis) 

3988 

3989 rdtype = _replace_dtype_fields(self.dtype, "O") 

3990 res = data.astype(rdtype) 

3991 _recursive_printoption(res, mask, masked_print_option) 

3992 else: 

3993 res = self.filled(self.fill_value) 

3994 return res 

3995 

3996 def __str__(self): 

3997 return str(self._insert_masked_print()) 

3998 

3999 def __repr__(self): 

4000 """ 

4001 Literal string representation. 

4002 

4003 """ 

4004 if self._baseclass is np.ndarray: 

4005 name = 'array' 

4006 else: 

4007 name = self._baseclass.__name__ 

4008 

4009 

4010 # 2016-11-19: Demoted to legacy format 

4011 if np.core.arrayprint._get_legacy_print_mode() <= 113: 

4012 is_long = self.ndim > 1 

4013 parameters = dict( 

4014 name=name, 

4015 nlen=" " * len(name), 

4016 data=str(self), 

4017 mask=str(self._mask), 

4018 fill=str(self.fill_value), 

4019 dtype=str(self.dtype) 

4020 ) 

4021 is_structured = bool(self.dtype.names) 

4022 key = '{}_{}'.format( 

4023 'long' if is_long else 'short', 

4024 'flx' if is_structured else 'std' 

4025 ) 

4026 return _legacy_print_templates[key] % parameters 

4027 

4028 prefix = f"masked_{name}(" 

4029 

4030 dtype_needed = ( 

4031 not np.core.arrayprint.dtype_is_implied(self.dtype) or 

4032 np.all(self.mask) or 

4033 self.size == 0 

4034 ) 

4035 

4036 # determine which keyword args need to be shown 

4037 keys = ['data', 'mask', 'fill_value'] 

4038 if dtype_needed: 

4039 keys.append('dtype') 

4040 

4041 # array has only one row (non-column) 

4042 is_one_row = builtins.all(dim == 1 for dim in self.shape[:-1]) 

4043 

4044 # choose what to indent each keyword with 

4045 min_indent = 2 

4046 if is_one_row: 

4047 # first key on the same line as the type, remaining keys 

4048 # aligned by equals 

4049 indents = {} 

4050 indents[keys[0]] = prefix 

4051 for k in keys[1:]: 

4052 n = builtins.max(min_indent, len(prefix + keys[0]) - len(k)) 

4053 indents[k] = ' ' * n 

4054 prefix = '' # absorbed into the first indent 

4055 else: 

4056 # each key on its own line, indented by two spaces 

4057 indents = {k: ' ' * min_indent for k in keys} 

4058 prefix = prefix + '\n' # first key on the next line 

4059 

4060 # format the field values 

4061 reprs = {} 

4062 reprs['data'] = np.array2string( 

4063 self._insert_masked_print(), 

4064 separator=", ", 

4065 prefix=indents['data'] + 'data=', 

4066 suffix=',') 

4067 reprs['mask'] = np.array2string( 

4068 self._mask, 

4069 separator=", ", 

4070 prefix=indents['mask'] + 'mask=', 

4071 suffix=',') 

4072 reprs['fill_value'] = repr(self.fill_value) 

4073 if dtype_needed: 

4074 reprs['dtype'] = np.core.arrayprint.dtype_short_repr(self.dtype) 

4075 

4076 # join keys with values and indentations 

4077 result = ',\n'.join( 

4078 '{}{}={}'.format(indents[k], k, reprs[k]) 

4079 for k in keys 

4080 ) 

4081 return prefix + result + ')' 

4082 

4083 def _delegate_binop(self, other): 

4084 # This emulates the logic in 

4085 # private/binop_override.h:forward_binop_should_defer 

4086 if isinstance(other, type(self)): 

4087 return False 

4088 array_ufunc = getattr(other, "__array_ufunc__", False) 

4089 if array_ufunc is False: 

4090 other_priority = getattr(other, "__array_priority__", -1000000) 

4091 return self.__array_priority__ < other_priority 

4092 else: 

4093 # If array_ufunc is not None, it will be called inside the ufunc; 

4094 # None explicitly tells us to not call the ufunc, i.e., defer. 

4095 return array_ufunc is None 

4096 

4097 def _comparison(self, other, compare): 

4098 """Compare self with other using operator.eq or operator.ne. 

4099 

4100 When either of the elements is masked, the result is masked as well, 

4101 but the underlying boolean data are still set, with self and other 

4102 considered equal if both are masked, and unequal otherwise. 

4103 

4104 For structured arrays, all fields are combined, with masked values 

4105 ignored. The result is masked if all fields were masked, with self 

4106 and other considered equal only if both were fully masked. 

4107 """ 

4108 omask = getmask(other) 

4109 smask = self.mask 

4110 mask = mask_or(smask, omask, copy=True) 

4111 

4112 odata = getdata(other) 

4113 if mask.dtype.names is not None: 

4114 # only == and != are reasonably defined for structured dtypes, 

4115 # so give up early for all other comparisons: 

4116 if compare not in (operator.eq, operator.ne): 

4117 return NotImplemented 

4118 # For possibly masked structured arrays we need to be careful, 

4119 # since the standard structured array comparison will use all 

4120 # fields, masked or not. To avoid masked fields influencing the 

4121 # outcome, we set all masked fields in self to other, so they'll 

4122 # count as equal. To prepare, we ensure we have the right shape. 

4123 broadcast_shape = np.broadcast(self, odata).shape 

4124 sbroadcast = np.broadcast_to(self, broadcast_shape, subok=True) 

4125 sbroadcast._mask = mask 

4126 sdata = sbroadcast.filled(odata) 

4127 # Now take care of the mask; the merged mask should have an item 

4128 # masked if all fields were masked (in one and/or other). 

4129 mask = (mask == np.ones((), mask.dtype)) 

4130 # Ensure we can compare masks below if other was not masked. 

4131 if omask is np.False_: 

4132 omask = np.zeros((), smask.dtype) 

4133 

4134 else: 

4135 # For regular arrays, just use the data as they come. 

4136 sdata = self.data 

4137 

4138 check = compare(sdata, odata) 

4139 

4140 if isinstance(check, (np.bool_, bool)): 

4141 return masked if mask else check 

4142 

4143 if mask is not nomask: 

4144 if compare in (operator.eq, operator.ne): 

4145 # Adjust elements that were masked, which should be treated 

4146 # as equal if masked in both, unequal if masked in one. 

4147 # Note that this works automatically for structured arrays too. 

4148 # Ignore this for operations other than `==` and `!=` 

4149 check = np.where(mask, compare(smask, omask), check) 

4150 

4151 if mask.shape != check.shape: 

4152 # Guarantee consistency of the shape, making a copy since the 

4153 # the mask may need to get written to later. 

4154 mask = np.broadcast_to(mask, check.shape).copy() 

4155 

4156 check = check.view(type(self)) 

4157 check._update_from(self) 

4158 check._mask = mask 

4159 

4160 # Cast fill value to bool_ if needed. If it cannot be cast, the 

4161 # default boolean fill value is used. 

4162 if check._fill_value is not None: 

4163 try: 

4164 fill = _check_fill_value(check._fill_value, np.bool_) 

4165 except (TypeError, ValueError): 

4166 fill = _check_fill_value(None, np.bool_) 

4167 check._fill_value = fill 

4168 

4169 return check 

4170 

4171 def __eq__(self, other): 

4172 """Check whether other equals self elementwise. 

4173 

4174 When either of the elements is masked, the result is masked as well, 

4175 but the underlying boolean data are still set, with self and other 

4176 considered equal if both are masked, and unequal otherwise. 

4177 

4178 For structured arrays, all fields are combined, with masked values 

4179 ignored. The result is masked if all fields were masked, with self 

4180 and other considered equal only if both were fully masked. 

4181 """ 

4182 return self._comparison(other, operator.eq) 

4183 

4184 def __ne__(self, other): 

4185 """Check whether other does not equal self elementwise. 

4186 

4187 When either of the elements is masked, the result is masked as well, 

4188 but the underlying boolean data are still set, with self and other 

4189 considered equal if both are masked, and unequal otherwise. 

4190 

4191 For structured arrays, all fields are combined, with masked values 

4192 ignored. The result is masked if all fields were masked, with self 

4193 and other considered equal only if both were fully masked. 

4194 """ 

4195 return self._comparison(other, operator.ne) 

4196 

4197 # All other comparisons: 

4198 def __le__(self, other): 

4199 return self._comparison(other, operator.le) 

4200 

4201 def __lt__(self, other): 

4202 return self._comparison(other, operator.lt) 

4203 

4204 def __ge__(self, other): 

4205 return self._comparison(other, operator.ge) 

4206 

4207 def __gt__(self, other): 

4208 return self._comparison(other, operator.gt) 

4209 

4210 def __add__(self, other): 

4211 """ 

4212 Add self to other, and return a new masked array. 

4213 

4214 """ 

4215 if self._delegate_binop(other): 

4216 return NotImplemented 

4217 return add(self, other) 

4218 

4219 def __radd__(self, other): 

4220 """ 

4221 Add other to self, and return a new masked array. 

4222 

4223 """ 

4224 # In analogy with __rsub__ and __rdiv__, use original order: 

4225 # we get here from `other + self`. 

4226 return add(other, self) 

4227 

4228 def __sub__(self, other): 

4229 """ 

4230 Subtract other from self, and return a new masked array. 

4231 

4232 """ 

4233 if self._delegate_binop(other): 

4234 return NotImplemented 

4235 return subtract(self, other) 

4236 

4237 def __rsub__(self, other): 

4238 """ 

4239 Subtract self from other, and return a new masked array. 

4240 

4241 """ 

4242 return subtract(other, self) 

4243 

4244 def __mul__(self, other): 

4245 "Multiply self by other, and return a new masked array." 

4246 if self._delegate_binop(other): 

4247 return NotImplemented 

4248 return multiply(self, other) 

4249 

4250 def __rmul__(self, other): 

4251 """ 

4252 Multiply other by self, and return a new masked array. 

4253 

4254 """ 

4255 # In analogy with __rsub__ and __rdiv__, use original order: 

4256 # we get here from `other * self`. 

4257 return multiply(other, self) 

4258 

4259 def __div__(self, other): 

4260 """ 

4261 Divide other into self, and return a new masked array. 

4262 

4263 """ 

4264 if self._delegate_binop(other): 

4265 return NotImplemented 

4266 return divide(self, other) 

4267 

4268 def __truediv__(self, other): 

4269 """ 

4270 Divide other into self, and return a new masked array. 

4271 

4272 """ 

4273 if self._delegate_binop(other): 

4274 return NotImplemented 

4275 return true_divide(self, other) 

4276 

4277 def __rtruediv__(self, other): 

4278 """ 

4279 Divide self into other, and return a new masked array. 

4280 

4281 """ 

4282 return true_divide(other, self) 

4283 

4284 def __floordiv__(self, other): 

4285 """ 

4286 Divide other into self, and return a new masked array. 

4287 

4288 """ 

4289 if self._delegate_binop(other): 

4290 return NotImplemented 

4291 return floor_divide(self, other) 

4292 

4293 def __rfloordiv__(self, other): 

4294 """ 

4295 Divide self into other, and return a new masked array. 

4296 

4297 """ 

4298 return floor_divide(other, self) 

4299 

4300 def __pow__(self, other): 

4301 """ 

4302 Raise self to the power other, masking the potential NaNs/Infs 

4303 

4304 """ 

4305 if self._delegate_binop(other): 

4306 return NotImplemented 

4307 return power(self, other) 

4308 

4309 def __rpow__(self, other): 

4310 """ 

4311 Raise other to the power self, masking the potential NaNs/Infs 

4312 

4313 """ 

4314 return power(other, self) 

4315 

4316 def __iadd__(self, other): 

4317 """ 

4318 Add other to self in-place. 

4319 

4320 """ 

4321 m = getmask(other) 

4322 if self._mask is nomask: 

4323 if m is not nomask and m.any(): 

4324 self._mask = make_mask_none(self.shape, self.dtype) 

4325 self._mask += m 

4326 else: 

4327 if m is not nomask: 

4328 self._mask += m 

4329 other_data = getdata(other) 

4330 other_data = np.where(self._mask, other_data.dtype.type(0), other_data) 

4331 self._data.__iadd__(other_data) 

4332 return self 

4333 

4334 def __isub__(self, other): 

4335 """ 

4336 Subtract other from self in-place. 

4337 

4338 """ 

4339 m = getmask(other) 

4340 if self._mask is nomask: 

4341 if m is not nomask and m.any(): 

4342 self._mask = make_mask_none(self.shape, self.dtype) 

4343 self._mask += m 

4344 elif m is not nomask: 

4345 self._mask += m 

4346 other_data = getdata(other) 

4347 other_data = np.where(self._mask, other_data.dtype.type(0), other_data) 

4348 self._data.__isub__(other_data) 

4349 return self 

4350 

4351 def __imul__(self, other): 

4352 """ 

4353 Multiply self by other in-place. 

4354 

4355 """ 

4356 m = getmask(other) 

4357 if self._mask is nomask: 

4358 if m is not nomask and m.any(): 

4359 self._mask = make_mask_none(self.shape, self.dtype) 

4360 self._mask += m 

4361 elif m is not nomask: 

4362 self._mask += m 

4363 other_data = getdata(other) 

4364 other_data = np.where(self._mask, other_data.dtype.type(1), other_data) 

4365 self._data.__imul__(other_data) 

4366 return self 

4367 

4368 def __idiv__(self, other): 

4369 """ 

4370 Divide self by other in-place. 

4371 

4372 """ 

4373 other_data = getdata(other) 

4374 dom_mask = _DomainSafeDivide().__call__(self._data, other_data) 

4375 other_mask = getmask(other) 

4376 new_mask = mask_or(other_mask, dom_mask) 

4377 # The following 4 lines control the domain filling 

4378 if dom_mask.any(): 

4379 (_, fval) = ufunc_fills[np.divide] 

4380 other_data = np.where( 

4381 dom_mask, other_data.dtype.type(fval), other_data) 

4382 self._mask |= new_mask 

4383 other_data = np.where(self._mask, other_data.dtype.type(1), other_data) 

4384 self._data.__idiv__(other_data) 

4385 return self 

4386 

4387 def __ifloordiv__(self, other): 

4388 """ 

4389 Floor divide self by other in-place. 

4390 

4391 """ 

4392 other_data = getdata(other) 

4393 dom_mask = _DomainSafeDivide().__call__(self._data, other_data) 

4394 other_mask = getmask(other) 

4395 new_mask = mask_or(other_mask, dom_mask) 

4396 # The following 3 lines control the domain filling 

4397 if dom_mask.any(): 

4398 (_, fval) = ufunc_fills[np.floor_divide] 

4399 other_data = np.where( 

4400 dom_mask, other_data.dtype.type(fval), other_data) 

4401 self._mask |= new_mask 

4402 other_data = np.where(self._mask, other_data.dtype.type(1), other_data) 

4403 self._data.__ifloordiv__(other_data) 

4404 return self 

4405 

4406 def __itruediv__(self, other): 

4407 """ 

4408 True divide self by other in-place. 

4409 

4410 """ 

4411 other_data = getdata(other) 

4412 dom_mask = _DomainSafeDivide().__call__(self._data, other_data) 

4413 other_mask = getmask(other) 

4414 new_mask = mask_or(other_mask, dom_mask) 

4415 # The following 3 lines control the domain filling 

4416 if dom_mask.any(): 

4417 (_, fval) = ufunc_fills[np.true_divide] 

4418 other_data = np.where( 

4419 dom_mask, other_data.dtype.type(fval), other_data) 

4420 self._mask |= new_mask 

4421 other_data = np.where(self._mask, other_data.dtype.type(1), other_data) 

4422 self._data.__itruediv__(other_data) 

4423 return self 

4424 

4425 def __ipow__(self, other): 

4426 """ 

4427 Raise self to the power other, in place. 

4428 

4429 """ 

4430 other_data = getdata(other) 

4431 other_data = np.where(self._mask, other_data.dtype.type(1), other_data) 

4432 other_mask = getmask(other) 

4433 with np.errstate(divide='ignore', invalid='ignore'): 

4434 self._data.__ipow__(other_data) 

4435 invalid = np.logical_not(np.isfinite(self._data)) 

4436 if invalid.any(): 

4437 if self._mask is not nomask: 

4438 self._mask |= invalid 

4439 else: 

4440 self._mask = invalid 

4441 np.copyto(self._data, self.fill_value, where=invalid) 

4442 new_mask = mask_or(other_mask, invalid) 

4443 self._mask = mask_or(self._mask, new_mask) 

4444 return self 

4445 

4446 def __float__(self): 

4447 """ 

4448 Convert to float. 

4449 

4450 """ 

4451 if self.size > 1: 

4452 raise TypeError("Only length-1 arrays can be converted " 

4453 "to Python scalars") 

4454 elif self._mask: 

4455 warnings.warn("Warning: converting a masked element to nan.", stacklevel=2) 

4456 return np.nan 

4457 return float(self.item()) 

4458 

4459 def __int__(self): 

4460 """ 

4461 Convert to int. 

4462 

4463 """ 

4464 if self.size > 1: 

4465 raise TypeError("Only length-1 arrays can be converted " 

4466 "to Python scalars") 

4467 elif self._mask: 

4468 raise MaskError('Cannot convert masked element to a Python int.') 

4469 return int(self.item()) 

4470 

4471 @property 

4472 def imag(self): 

4473 """ 

4474 The imaginary part of the masked array. 

4475 

4476 This property is a view on the imaginary part of this `MaskedArray`. 

4477 

4478 See Also 

4479 -------- 

4480 real 

4481 

4482 Examples 

4483 -------- 

4484 >>> x = np.ma.array([1+1.j, -2j, 3.45+1.6j], mask=[False, True, False]) 

4485 >>> x.imag 

4486 masked_array(data=[1.0, --, 1.6], 

4487 mask=[False, True, False], 

4488 fill_value=1e+20) 

4489 

4490 """ 

4491 result = self._data.imag.view(type(self)) 

4492 result.__setmask__(self._mask) 

4493 return result 

4494 

4495 # kept for compatibility 

4496 get_imag = imag.fget 

4497 

4498 @property 

4499 def real(self): 

4500 """ 

4501 The real part of the masked array. 

4502 

4503 This property is a view on the real part of this `MaskedArray`. 

4504 

4505 See Also 

4506 -------- 

4507 imag 

4508 

4509 Examples 

4510 -------- 

4511 >>> x = np.ma.array([1+1.j, -2j, 3.45+1.6j], mask=[False, True, False]) 

4512 >>> x.real 

4513 masked_array(data=[1.0, --, 3.45], 

4514 mask=[False, True, False], 

4515 fill_value=1e+20) 

4516 

4517 """ 

4518 result = self._data.real.view(type(self)) 

4519 result.__setmask__(self._mask) 

4520 return result 

4521 

4522 # kept for compatibility 

4523 get_real = real.fget 

4524 

4525 def count(self, axis=None, keepdims=np._NoValue): 

4526 """ 

4527 Count the non-masked elements of the array along the given axis. 

4528 

4529 Parameters 

4530 ---------- 

4531 axis : None or int or tuple of ints, optional 

4532 Axis or axes along which the count is performed. 

4533 The default, None, performs the count over all 

4534 the dimensions of the input array. `axis` may be negative, in 

4535 which case it counts from the last to the first axis. 

4536 

4537 .. versionadded:: 1.10.0 

4538 

4539 If this is a tuple of ints, the count is performed on multiple 

4540 axes, instead of a single axis or all the axes as before. 

4541 keepdims : bool, optional 

4542 If this is set to True, the axes which are reduced are left 

4543 in the result as dimensions with size one. With this option, 

4544 the result will broadcast correctly against the array. 

4545 

4546 Returns 

4547 ------- 

4548 result : ndarray or scalar 

4549 An array with the same shape as the input array, with the specified 

4550 axis removed. If the array is a 0-d array, or if `axis` is None, a 

4551 scalar is returned. 

4552 

4553 See Also 

4554 -------- 

4555 ma.count_masked : Count masked elements in array or along a given axis. 

4556 

4557 Examples 

4558 -------- 

4559 >>> import numpy.ma as ma 

4560 >>> a = ma.arange(6).reshape((2, 3)) 

4561 >>> a[1, :] = ma.masked 

4562 >>> a 

4563 masked_array( 

4564 data=[[0, 1, 2], 

4565 [--, --, --]], 

4566 mask=[[False, False, False], 

4567 [ True, True, True]], 

4568 fill_value=999999) 

4569 >>> a.count() 

4570 3 

4571 

4572 When the `axis` keyword is specified an array of appropriate size is 

4573 returned. 

4574 

4575 >>> a.count(axis=0) 

4576 array([1, 1, 1]) 

4577 >>> a.count(axis=1) 

4578 array([3, 0]) 

4579 

4580 """ 

4581 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

4582 

4583 m = self._mask 

4584 # special case for matrices (we assume no other subclasses modify 

4585 # their dimensions) 

4586 if isinstance(self.data, np.matrix): 

4587 if m is nomask: 

4588 m = np.zeros(self.shape, dtype=np.bool_) 

4589 m = m.view(type(self.data)) 

4590 

4591 if m is nomask: 

4592 # compare to _count_reduce_items in _methods.py 

4593 

4594 if self.shape == (): 

4595 if axis not in (None, 0): 

4596 raise np.AxisError(axis=axis, ndim=self.ndim) 

4597 return 1 

4598 elif axis is None: 

4599 if kwargs.get('keepdims', False): 

4600 return np.array(self.size, dtype=np.intp, ndmin=self.ndim) 

4601 return self.size 

4602 

4603 axes = normalize_axis_tuple(axis, self.ndim) 

4604 items = 1 

4605 for ax in axes: 

4606 items *= self.shape[ax] 

4607 

4608 if kwargs.get('keepdims', False): 

4609 out_dims = list(self.shape) 

4610 for a in axes: 

4611 out_dims[a] = 1 

4612 else: 

4613 out_dims = [d for n, d in enumerate(self.shape) 

4614 if n not in axes] 

4615 # make sure to return a 0-d array if axis is supplied 

4616 return np.full(out_dims, items, dtype=np.intp) 

4617 

4618 # take care of the masked singleton 

4619 if self is masked: 

4620 return 0 

4621 

4622 return (~m).sum(axis=axis, dtype=np.intp, **kwargs) 

4623 

4624 def ravel(self, order='C'): 

4625 """ 

4626 Returns a 1D version of self, as a view. 

4627 

4628 Parameters 

4629 ---------- 

4630 order : {'C', 'F', 'A', 'K'}, optional 

4631 The elements of `a` are read using this index order. 'C' means to 

4632 index the elements in C-like order, with the last axis index 

4633 changing fastest, back to the first axis index changing slowest. 

4634 'F' means to index the elements in Fortran-like index order, with 

4635 the first index changing fastest, and the last index changing 

4636 slowest. Note that the 'C' and 'F' options take no account of the 

4637 memory layout of the underlying array, and only refer to the order 

4638 of axis indexing. 'A' means to read the elements in Fortran-like 

4639 index order if `m` is Fortran *contiguous* in memory, C-like order 

4640 otherwise. 'K' means to read the elements in the order they occur 

4641 in memory, except for reversing the data when strides are negative. 

4642 By default, 'C' index order is used. 

4643 (Masked arrays currently use 'A' on the data when 'K' is passed.) 

4644 

4645 Returns 

4646 ------- 

4647 MaskedArray 

4648 Output view is of shape ``(self.size,)`` (or 

4649 ``(np.ma.product(self.shape),)``). 

4650 

4651 Examples 

4652 -------- 

4653 >>> x = np.ma.array([[1,2,3],[4,5,6],[7,8,9]], mask=[0] + [1,0]*4) 

4654 >>> x 

4655 masked_array( 

4656 data=[[1, --, 3], 

4657 [--, 5, --], 

4658 [7, --, 9]], 

4659 mask=[[False, True, False], 

4660 [ True, False, True], 

4661 [False, True, False]], 

4662 fill_value=999999) 

4663 >>> x.ravel() 

4664 masked_array(data=[1, --, 3, --, 5, --, 7, --, 9], 

4665 mask=[False, True, False, True, False, True, False, True, 

4666 False], 

4667 fill_value=999999) 

4668 

4669 """ 

4670 # The order of _data and _mask could be different (it shouldn't be 

4671 # normally). Passing order `K` or `A` would be incorrect. 

4672 # So we ignore the mask memory order. 

4673 # TODO: We don't actually support K, so use A instead. We could 

4674 # try to guess this correct by sorting strides or deprecate. 

4675 if order in "kKaA": 

4676 order = "F" if self._data.flags.fnc else "C" 

4677 r = ndarray.ravel(self._data, order=order).view(type(self)) 

4678 r._update_from(self) 

4679 if self._mask is not nomask: 

4680 r._mask = ndarray.ravel(self._mask, order=order).reshape(r.shape) 

4681 else: 

4682 r._mask = nomask 

4683 return r 

4684 

4685 

4686 def reshape(self, *s, **kwargs): 

4687 """ 

4688 Give a new shape to the array without changing its data. 

4689 

4690 Returns a masked array containing the same data, but with a new shape. 

4691 The result is a view on the original array; if this is not possible, a 

4692 ValueError is raised. 

4693 

4694 Parameters 

4695 ---------- 

4696 shape : int or tuple of ints 

4697 The new shape should be compatible with the original shape. If an 

4698 integer is supplied, then the result will be a 1-D array of that 

4699 length. 

4700 order : {'C', 'F'}, optional 

4701 Determines whether the array data should be viewed as in C 

4702 (row-major) or FORTRAN (column-major) order. 

4703 

4704 Returns 

4705 ------- 

4706 reshaped_array : array 

4707 A new view on the array. 

4708 

4709 See Also 

4710 -------- 

4711 reshape : Equivalent function in the masked array module. 

4712 numpy.ndarray.reshape : Equivalent method on ndarray object. 

4713 numpy.reshape : Equivalent function in the NumPy module. 

4714 

4715 Notes 

4716 ----- 

4717 The reshaping operation cannot guarantee that a copy will not be made, 

4718 to modify the shape in place, use ``a.shape = s`` 

4719 

4720 Examples 

4721 -------- 

4722 >>> x = np.ma.array([[1,2],[3,4]], mask=[1,0,0,1]) 

4723 >>> x 

4724 masked_array( 

4725 data=[[--, 2], 

4726 [3, --]], 

4727 mask=[[ True, False], 

4728 [False, True]], 

4729 fill_value=999999) 

4730 >>> x = x.reshape((4,1)) 

4731 >>> x 

4732 masked_array( 

4733 data=[[--], 

4734 [2], 

4735 [3], 

4736 [--]], 

4737 mask=[[ True], 

4738 [False], 

4739 [False], 

4740 [ True]], 

4741 fill_value=999999) 

4742 

4743 """ 

4744 kwargs.update(order=kwargs.get('order', 'C')) 

4745 result = self._data.reshape(*s, **kwargs).view(type(self)) 

4746 result._update_from(self) 

4747 mask = self._mask 

4748 if mask is not nomask: 

4749 result._mask = mask.reshape(*s, **kwargs) 

4750 return result 

4751 

4752 def resize(self, newshape, refcheck=True, order=False): 

4753 """ 

4754 .. warning:: 

4755 

4756 This method does nothing, except raise a ValueError exception. A 

4757 masked array does not own its data and therefore cannot safely be 

4758 resized in place. Use the `numpy.ma.resize` function instead. 

4759 

4760 This method is difficult to implement safely and may be deprecated in 

4761 future releases of NumPy. 

4762 

4763 """ 

4764 # Note : the 'order' keyword looks broken, let's just drop it 

4765 errmsg = "A masked array does not own its data "\ 

4766 "and therefore cannot be resized.\n" \ 

4767 "Use the numpy.ma.resize function instead." 

4768 raise ValueError(errmsg) 

4769 

4770 def put(self, indices, values, mode='raise'): 

4771 """ 

4772 Set storage-indexed locations to corresponding values. 

4773 

4774 Sets self._data.flat[n] = values[n] for each n in indices. 

4775 If `values` is shorter than `indices` then it will repeat. 

4776 If `values` has some masked values, the initial mask is updated 

4777 in consequence, else the corresponding values are unmasked. 

4778 

4779 Parameters 

4780 ---------- 

4781 indices : 1-D array_like 

4782 Target indices, interpreted as integers. 

4783 values : array_like 

4784 Values to place in self._data copy at target indices. 

4785 mode : {'raise', 'wrap', 'clip'}, optional 

4786 Specifies how out-of-bounds indices will behave. 

4787 'raise' : raise an error. 

4788 'wrap' : wrap around. 

4789 'clip' : clip to the range. 

4790 

4791 Notes 

4792 ----- 

4793 `values` can be a scalar or length 1 array. 

4794 

4795 Examples 

4796 -------- 

4797 >>> x = np.ma.array([[1,2,3],[4,5,6],[7,8,9]], mask=[0] + [1,0]*4) 

4798 >>> x 

4799 masked_array( 

4800 data=[[1, --, 3], 

4801 [--, 5, --], 

4802 [7, --, 9]], 

4803 mask=[[False, True, False], 

4804 [ True, False, True], 

4805 [False, True, False]], 

4806 fill_value=999999) 

4807 >>> x.put([0,4,8],[10,20,30]) 

4808 >>> x 

4809 masked_array( 

4810 data=[[10, --, 3], 

4811 [--, 20, --], 

4812 [7, --, 30]], 

4813 mask=[[False, True, False], 

4814 [ True, False, True], 

4815 [False, True, False]], 

4816 fill_value=999999) 

4817 

4818 >>> x.put(4,999) 

4819 >>> x 

4820 masked_array( 

4821 data=[[10, --, 3], 

4822 [--, 999, --], 

4823 [7, --, 30]], 

4824 mask=[[False, True, False], 

4825 [ True, False, True], 

4826 [False, True, False]], 

4827 fill_value=999999) 

4828 

4829 """ 

4830 # Hard mask: Get rid of the values/indices that fall on masked data 

4831 if self._hardmask and self._mask is not nomask: 

4832 mask = self._mask[indices] 

4833 indices = narray(indices, copy=False) 

4834 values = narray(values, copy=False, subok=True) 

4835 values.resize(indices.shape) 

4836 indices = indices[~mask] 

4837 values = values[~mask] 

4838 

4839 self._data.put(indices, values, mode=mode) 

4840 

4841 # short circuit if neither self nor values are masked 

4842 if self._mask is nomask and getmask(values) is nomask: 

4843 return 

4844 

4845 m = getmaskarray(self) 

4846 

4847 if getmask(values) is nomask: 

4848 m.put(indices, False, mode=mode) 

4849 else: 

4850 m.put(indices, values._mask, mode=mode) 

4851 m = make_mask(m, copy=False, shrink=True) 

4852 self._mask = m 

4853 return 

4854 

4855 def ids(self): 

4856 """ 

4857 Return the addresses of the data and mask areas. 

4858 

4859 Parameters 

4860 ---------- 

4861 None 

4862 

4863 Examples 

4864 -------- 

4865 >>> x = np.ma.array([1, 2, 3], mask=[0, 1, 1]) 

4866 >>> x.ids() 

4867 (166670640, 166659832) # may vary 

4868 

4869 If the array has no mask, the address of `nomask` is returned. This address 

4870 is typically not close to the data in memory: 

4871 

4872 >>> x = np.ma.array([1, 2, 3]) 

4873 >>> x.ids() 

4874 (166691080, 3083169284) # may vary 

4875 

4876 """ 

4877 if self._mask is nomask: 

4878 return (self.ctypes.data, id(nomask)) 

4879 return (self.ctypes.data, self._mask.ctypes.data) 

4880 

4881 def iscontiguous(self): 

4882 """ 

4883 Return a boolean indicating whether the data is contiguous. 

4884 

4885 Parameters 

4886 ---------- 

4887 None 

4888 

4889 Examples 

4890 -------- 

4891 >>> x = np.ma.array([1, 2, 3]) 

4892 >>> x.iscontiguous() 

4893 True 

4894 

4895 `iscontiguous` returns one of the flags of the masked array: 

4896 

4897 >>> x.flags 

4898 C_CONTIGUOUS : True 

4899 F_CONTIGUOUS : True 

4900 OWNDATA : False 

4901 WRITEABLE : True 

4902 ALIGNED : True 

4903 WRITEBACKIFCOPY : False 

4904 

4905 """ 

4906 return self.flags['CONTIGUOUS'] 

4907 

4908 def all(self, axis=None, out=None, keepdims=np._NoValue): 

4909 """ 

4910 Returns True if all elements evaluate to True. 

4911 

4912 The output array is masked where all the values along the given axis 

4913 are masked: if the output would have been a scalar and that all the 

4914 values are masked, then the output is `masked`. 

4915 

4916 Refer to `numpy.all` for full documentation. 

4917 

4918 See Also 

4919 -------- 

4920 numpy.ndarray.all : corresponding function for ndarrays 

4921 numpy.all : equivalent function 

4922 

4923 Examples 

4924 -------- 

4925 >>> np.ma.array([1,2,3]).all() 

4926 True 

4927 >>> a = np.ma.array([1,2,3], mask=True) 

4928 >>> (a.all() is np.ma.masked) 

4929 True 

4930 

4931 """ 

4932 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

4933 

4934 mask = _check_mask_axis(self._mask, axis, **kwargs) 

4935 if out is None: 

4936 d = self.filled(True).all(axis=axis, **kwargs).view(type(self)) 

4937 if d.ndim: 

4938 d.__setmask__(mask) 

4939 elif mask: 

4940 return masked 

4941 return d 

4942 self.filled(True).all(axis=axis, out=out, **kwargs) 

4943 if isinstance(out, MaskedArray): 

4944 if out.ndim or mask: 

4945 out.__setmask__(mask) 

4946 return out 

4947 

4948 def any(self, axis=None, out=None, keepdims=np._NoValue): 

4949 """ 

4950 Returns True if any of the elements of `a` evaluate to True. 

4951 

4952 Masked values are considered as False during computation. 

4953 

4954 Refer to `numpy.any` for full documentation. 

4955 

4956 See Also 

4957 -------- 

4958 numpy.ndarray.any : corresponding function for ndarrays 

4959 numpy.any : equivalent function 

4960 

4961 """ 

4962 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

4963 

4964 mask = _check_mask_axis(self._mask, axis, **kwargs) 

4965 if out is None: 

4966 d = self.filled(False).any(axis=axis, **kwargs).view(type(self)) 

4967 if d.ndim: 

4968 d.__setmask__(mask) 

4969 elif mask: 

4970 d = masked 

4971 return d 

4972 self.filled(False).any(axis=axis, out=out, **kwargs) 

4973 if isinstance(out, MaskedArray): 

4974 if out.ndim or mask: 

4975 out.__setmask__(mask) 

4976 return out 

4977 

4978 def nonzero(self): 

4979 """ 

4980 Return the indices of unmasked elements that are not zero. 

4981 

4982 Returns a tuple of arrays, one for each dimension, containing the 

4983 indices of the non-zero elements in that dimension. The corresponding 

4984 non-zero values can be obtained with:: 

4985 

4986 a[a.nonzero()] 

4987 

4988 To group the indices by element, rather than dimension, use 

4989 instead:: 

4990 

4991 np.transpose(a.nonzero()) 

4992 

4993 The result of this is always a 2d array, with a row for each non-zero 

4994 element. 

4995 

4996 Parameters 

4997 ---------- 

4998 None 

4999 

5000 Returns 

5001 ------- 

5002 tuple_of_arrays : tuple 

5003 Indices of elements that are non-zero. 

5004 

5005 See Also 

5006 -------- 

5007 numpy.nonzero : 

5008 Function operating on ndarrays. 

5009 flatnonzero : 

5010 Return indices that are non-zero in the flattened version of the input 

5011 array. 

5012 numpy.ndarray.nonzero : 

5013 Equivalent ndarray method. 

5014 count_nonzero : 

5015 Counts the number of non-zero elements in the input array. 

5016 

5017 Examples 

5018 -------- 

5019 >>> import numpy.ma as ma 

5020 >>> x = ma.array(np.eye(3)) 

5021 >>> x 

5022 masked_array( 

5023 data=[[1., 0., 0.], 

5024 [0., 1., 0.], 

5025 [0., 0., 1.]], 

5026 mask=False, 

5027 fill_value=1e+20) 

5028 >>> x.nonzero() 

5029 (array([0, 1, 2]), array([0, 1, 2])) 

5030 

5031 Masked elements are ignored. 

5032 

5033 >>> x[1, 1] = ma.masked 

5034 >>> x 

5035 masked_array( 

5036 data=[[1.0, 0.0, 0.0], 

5037 [0.0, --, 0.0], 

5038 [0.0, 0.0, 1.0]], 

5039 mask=[[False, False, False], 

5040 [False, True, False], 

5041 [False, False, False]], 

5042 fill_value=1e+20) 

5043 >>> x.nonzero() 

5044 (array([0, 2]), array([0, 2])) 

5045 

5046 Indices can also be grouped by element. 

5047 

5048 >>> np.transpose(x.nonzero()) 

5049 array([[0, 0], 

5050 [2, 2]]) 

5051 

5052 A common use for ``nonzero`` is to find the indices of an array, where 

5053 a condition is True. Given an array `a`, the condition `a` > 3 is a 

5054 boolean array and since False is interpreted as 0, ma.nonzero(a > 3) 

5055 yields the indices of the `a` where the condition is true. 

5056 

5057 >>> a = ma.array([[1,2,3],[4,5,6],[7,8,9]]) 

5058 >>> a > 3 

5059 masked_array( 

5060 data=[[False, False, False], 

5061 [ True, True, True], 

5062 [ True, True, True]], 

5063 mask=False, 

5064 fill_value=True) 

5065 >>> ma.nonzero(a > 3) 

5066 (array([1, 1, 1, 2, 2, 2]), array([0, 1, 2, 0, 1, 2])) 

5067 

5068 The ``nonzero`` method of the condition array can also be called. 

5069 

5070 >>> (a > 3).nonzero() 

5071 (array([1, 1, 1, 2, 2, 2]), array([0, 1, 2, 0, 1, 2])) 

5072 

5073 """ 

5074 return narray(self.filled(0), copy=False).nonzero() 

5075 

5076 def trace(self, offset=0, axis1=0, axis2=1, dtype=None, out=None): 

5077 """ 

5078 (this docstring should be overwritten) 

5079 """ 

5080 #!!!: implement out + test! 

5081 m = self._mask 

5082 if m is nomask: 

5083 result = super().trace(offset=offset, axis1=axis1, axis2=axis2, 

5084 out=out) 

5085 return result.astype(dtype) 

5086 else: 

5087 D = self.diagonal(offset=offset, axis1=axis1, axis2=axis2) 

5088 return D.astype(dtype).filled(0).sum(axis=-1, out=out) 

5089 trace.__doc__ = ndarray.trace.__doc__ 

5090 

5091 def dot(self, b, out=None, strict=False): 

5092 """ 

5093 a.dot(b, out=None) 

5094 

5095 Masked dot product of two arrays. Note that `out` and `strict` are 

5096 located in different positions than in `ma.dot`. In order to 

5097 maintain compatibility with the functional version, it is 

5098 recommended that the optional arguments be treated as keyword only. 

5099 At some point that may be mandatory. 

5100 

5101 .. versionadded:: 1.10.0 

5102 

5103 Parameters 

5104 ---------- 

5105 b : masked_array_like 

5106 Inputs array. 

5107 out : masked_array, optional 

5108 Output argument. This must have the exact kind that would be 

5109 returned if it was not used. In particular, it must have the 

5110 right type, must be C-contiguous, and its dtype must be the 

5111 dtype that would be returned for `ma.dot(a,b)`. This is a 

5112 performance feature. Therefore, if these conditions are not 

5113 met, an exception is raised, instead of attempting to be 

5114 flexible. 

5115 strict : bool, optional 

5116 Whether masked data are propagated (True) or set to 0 (False) 

5117 for the computation. Default is False. Propagating the mask 

5118 means that if a masked value appears in a row or column, the 

5119 whole row or column is considered masked. 

5120 

5121 .. versionadded:: 1.10.2 

5122 

5123 See Also 

5124 -------- 

5125 numpy.ma.dot : equivalent function 

5126 

5127 """ 

5128 return dot(self, b, out=out, strict=strict) 

5129 

5130 def sum(self, axis=None, dtype=None, out=None, keepdims=np._NoValue): 

5131 """ 

5132 Return the sum of the array elements over the given axis. 

5133 

5134 Masked elements are set to 0 internally. 

5135 

5136 Refer to `numpy.sum` for full documentation. 

5137 

5138 See Also 

5139 -------- 

5140 numpy.ndarray.sum : corresponding function for ndarrays 

5141 numpy.sum : equivalent function 

5142 

5143 Examples 

5144 -------- 

5145 >>> x = np.ma.array([[1,2,3],[4,5,6],[7,8,9]], mask=[0] + [1,0]*4) 

5146 >>> x 

5147 masked_array( 

5148 data=[[1, --, 3], 

5149 [--, 5, --], 

5150 [7, --, 9]], 

5151 mask=[[False, True, False], 

5152 [ True, False, True], 

5153 [False, True, False]], 

5154 fill_value=999999) 

5155 >>> x.sum() 

5156 25 

5157 >>> x.sum(axis=1) 

5158 masked_array(data=[4, 5, 16], 

5159 mask=[False, False, False], 

5160 fill_value=999999) 

5161 >>> x.sum(axis=0) 

5162 masked_array(data=[8, 5, 12], 

5163 mask=[False, False, False], 

5164 fill_value=999999) 

5165 >>> print(type(x.sum(axis=0, dtype=np.int64)[0])) 

5166 <class 'numpy.int64'> 

5167 

5168 """ 

5169 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

5170 

5171 _mask = self._mask 

5172 newmask = _check_mask_axis(_mask, axis, **kwargs) 

5173 # No explicit output 

5174 if out is None: 

5175 result = self.filled(0).sum(axis, dtype=dtype, **kwargs) 

5176 rndim = getattr(result, 'ndim', 0) 

5177 if rndim: 

5178 result = result.view(type(self)) 

5179 result.__setmask__(newmask) 

5180 elif newmask: 

5181 result = masked 

5182 return result 

5183 # Explicit output 

5184 result = self.filled(0).sum(axis, dtype=dtype, out=out, **kwargs) 

5185 if isinstance(out, MaskedArray): 

5186 outmask = getmask(out) 

5187 if outmask is nomask: 

5188 outmask = out._mask = make_mask_none(out.shape) 

5189 outmask.flat = newmask 

5190 return out 

5191 

5192 def cumsum(self, axis=None, dtype=None, out=None): 

5193 """ 

5194 Return the cumulative sum of the array elements over the given axis. 

5195 

5196 Masked values are set to 0 internally during the computation. 

5197 However, their position is saved, and the result will be masked at 

5198 the same locations. 

5199 

5200 Refer to `numpy.cumsum` for full documentation. 

5201 

5202 Notes 

5203 ----- 

5204 The mask is lost if `out` is not a valid :class:`ma.MaskedArray` ! 

5205 

5206 Arithmetic is modular when using integer types, and no error is 

5207 raised on overflow. 

5208 

5209 See Also 

5210 -------- 

5211 numpy.ndarray.cumsum : corresponding function for ndarrays 

5212 numpy.cumsum : equivalent function 

5213 

5214 Examples 

5215 -------- 

5216 >>> marr = np.ma.array(np.arange(10), mask=[0,0,0,1,1,1,0,0,0,0]) 

5217 >>> marr.cumsum() 

5218 masked_array(data=[0, 1, 3, --, --, --, 9, 16, 24, 33], 

5219 mask=[False, False, False, True, True, True, False, False, 

5220 False, False], 

5221 fill_value=999999) 

5222 

5223 """ 

5224 result = self.filled(0).cumsum(axis=axis, dtype=dtype, out=out) 

5225 if out is not None: 

5226 if isinstance(out, MaskedArray): 

5227 out.__setmask__(self.mask) 

5228 return out 

5229 result = result.view(type(self)) 

5230 result.__setmask__(self._mask) 

5231 return result 

5232 

5233 def prod(self, axis=None, dtype=None, out=None, keepdims=np._NoValue): 

5234 """ 

5235 Return the product of the array elements over the given axis. 

5236 

5237 Masked elements are set to 1 internally for computation. 

5238 

5239 Refer to `numpy.prod` for full documentation. 

5240 

5241 Notes 

5242 ----- 

5243 Arithmetic is modular when using integer types, and no error is raised 

5244 on overflow. 

5245 

5246 See Also 

5247 -------- 

5248 numpy.ndarray.prod : corresponding function for ndarrays 

5249 numpy.prod : equivalent function 

5250 """ 

5251 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

5252 

5253 _mask = self._mask 

5254 newmask = _check_mask_axis(_mask, axis, **kwargs) 

5255 # No explicit output 

5256 if out is None: 

5257 result = self.filled(1).prod(axis, dtype=dtype, **kwargs) 

5258 rndim = getattr(result, 'ndim', 0) 

5259 if rndim: 

5260 result = result.view(type(self)) 

5261 result.__setmask__(newmask) 

5262 elif newmask: 

5263 result = masked 

5264 return result 

5265 # Explicit output 

5266 result = self.filled(1).prod(axis, dtype=dtype, out=out, **kwargs) 

5267 if isinstance(out, MaskedArray): 

5268 outmask = getmask(out) 

5269 if outmask is nomask: 

5270 outmask = out._mask = make_mask_none(out.shape) 

5271 outmask.flat = newmask 

5272 return out 

5273 product = prod 

5274 

5275 def cumprod(self, axis=None, dtype=None, out=None): 

5276 """ 

5277 Return the cumulative product of the array elements over the given axis. 

5278 

5279 Masked values are set to 1 internally during the computation. 

5280 However, their position is saved, and the result will be masked at 

5281 the same locations. 

5282 

5283 Refer to `numpy.cumprod` for full documentation. 

5284 

5285 Notes 

5286 ----- 

5287 The mask is lost if `out` is not a valid MaskedArray ! 

5288 

5289 Arithmetic is modular when using integer types, and no error is 

5290 raised on overflow. 

5291 

5292 See Also 

5293 -------- 

5294 numpy.ndarray.cumprod : corresponding function for ndarrays 

5295 numpy.cumprod : equivalent function 

5296 """ 

5297 result = self.filled(1).cumprod(axis=axis, dtype=dtype, out=out) 

5298 if out is not None: 

5299 if isinstance(out, MaskedArray): 

5300 out.__setmask__(self._mask) 

5301 return out 

5302 result = result.view(type(self)) 

5303 result.__setmask__(self._mask) 

5304 return result 

5305 

5306 def mean(self, axis=None, dtype=None, out=None, keepdims=np._NoValue): 

5307 """ 

5308 Returns the average of the array elements along given axis. 

5309 

5310 Masked entries are ignored, and result elements which are not 

5311 finite will be masked. 

5312 

5313 Refer to `numpy.mean` for full documentation. 

5314 

5315 See Also 

5316 -------- 

5317 numpy.ndarray.mean : corresponding function for ndarrays 

5318 numpy.mean : Equivalent function 

5319 numpy.ma.average : Weighted average. 

5320 

5321 Examples 

5322 -------- 

5323 >>> a = np.ma.array([1,2,3], mask=[False, False, True]) 

5324 >>> a 

5325 masked_array(data=[1, 2, --], 

5326 mask=[False, False, True], 

5327 fill_value=999999) 

5328 >>> a.mean() 

5329 1.5 

5330 

5331 """ 

5332 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

5333 if self._mask is nomask: 

5334 result = super().mean(axis=axis, dtype=dtype, **kwargs)[()] 

5335 else: 

5336 is_float16_result = False 

5337 if dtype is None: 

5338 if issubclass(self.dtype.type, (ntypes.integer, ntypes.bool_)): 

5339 dtype = mu.dtype('f8') 

5340 elif issubclass(self.dtype.type, ntypes.float16): 

5341 dtype = mu.dtype('f4') 

5342 is_float16_result = True 

5343 dsum = self.sum(axis=axis, dtype=dtype, **kwargs) 

5344 cnt = self.count(axis=axis, **kwargs) 

5345 if cnt.shape == () and (cnt == 0): 

5346 result = masked 

5347 elif is_float16_result: 

5348 result = self.dtype.type(dsum * 1. / cnt) 

5349 else: 

5350 result = dsum * 1. / cnt 

5351 if out is not None: 

5352 out.flat = result 

5353 if isinstance(out, MaskedArray): 

5354 outmask = getmask(out) 

5355 if outmask is nomask: 

5356 outmask = out._mask = make_mask_none(out.shape) 

5357 outmask.flat = getmask(result) 

5358 return out 

5359 return result 

5360 

5361 def anom(self, axis=None, dtype=None): 

5362 """ 

5363 Compute the anomalies (deviations from the arithmetic mean) 

5364 along the given axis. 

5365 

5366 Returns an array of anomalies, with the same shape as the input and 

5367 where the arithmetic mean is computed along the given axis. 

5368 

5369 Parameters 

5370 ---------- 

5371 axis : int, optional 

5372 Axis over which the anomalies are taken. 

5373 The default is to use the mean of the flattened array as reference. 

5374 dtype : dtype, optional 

5375 Type to use in computing the variance. For arrays of integer type 

5376 the default is float32; for arrays of float types it is the same as 

5377 the array type. 

5378 

5379 See Also 

5380 -------- 

5381 mean : Compute the mean of the array. 

5382 

5383 Examples 

5384 -------- 

5385 >>> a = np.ma.array([1,2,3]) 

5386 >>> a.anom() 

5387 masked_array(data=[-1., 0., 1.], 

5388 mask=False, 

5389 fill_value=1e+20) 

5390 

5391 """ 

5392 m = self.mean(axis, dtype) 

5393 if not axis: 

5394 return self - m 

5395 else: 

5396 return self - expand_dims(m, axis) 

5397 

5398 def var(self, axis=None, dtype=None, out=None, ddof=0, 

5399 keepdims=np._NoValue): 

5400 """ 

5401 Returns the variance of the array elements along given axis. 

5402 

5403 Masked entries are ignored, and result elements which are not 

5404 finite will be masked. 

5405 

5406 Refer to `numpy.var` for full documentation. 

5407 

5408 See Also 

5409 -------- 

5410 numpy.ndarray.var : corresponding function for ndarrays 

5411 numpy.var : Equivalent function 

5412 """ 

5413 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

5414 

5415 # Easy case: nomask, business as usual 

5416 if self._mask is nomask: 

5417 ret = super().var(axis=axis, dtype=dtype, out=out, ddof=ddof, 

5418 **kwargs)[()] 

5419 if out is not None: 

5420 if isinstance(out, MaskedArray): 

5421 out.__setmask__(nomask) 

5422 return out 

5423 return ret 

5424 

5425 # Some data are masked, yay! 

5426 cnt = self.count(axis=axis, **kwargs) - ddof 

5427 danom = self - self.mean(axis, dtype, keepdims=True) 

5428 if iscomplexobj(self): 

5429 danom = umath.absolute(danom) ** 2 

5430 else: 

5431 danom *= danom 

5432 dvar = divide(danom.sum(axis, **kwargs), cnt).view(type(self)) 

5433 # Apply the mask if it's not a scalar 

5434 if dvar.ndim: 

5435 dvar._mask = mask_or(self._mask.all(axis, **kwargs), (cnt <= 0)) 

5436 dvar._update_from(self) 

5437 elif getmask(dvar): 

5438 # Make sure that masked is returned when the scalar is masked. 

5439 dvar = masked 

5440 if out is not None: 

5441 if isinstance(out, MaskedArray): 

5442 out.flat = 0 

5443 out.__setmask__(True) 

5444 elif out.dtype.kind in 'biu': 

5445 errmsg = "Masked data information would be lost in one or "\ 

5446 "more location." 

5447 raise MaskError(errmsg) 

5448 else: 

5449 out.flat = np.nan 

5450 return out 

5451 # In case with have an explicit output 

5452 if out is not None: 

5453 # Set the data 

5454 out.flat = dvar 

5455 # Set the mask if needed 

5456 if isinstance(out, MaskedArray): 

5457 out.__setmask__(dvar.mask) 

5458 return out 

5459 return dvar 

5460 var.__doc__ = np.var.__doc__ 

5461 

5462 def std(self, axis=None, dtype=None, out=None, ddof=0, 

5463 keepdims=np._NoValue): 

5464 """ 

5465 Returns the standard deviation of the array elements along given axis. 

5466 

5467 Masked entries are ignored. 

5468 

5469 Refer to `numpy.std` for full documentation. 

5470 

5471 See Also 

5472 -------- 

5473 numpy.ndarray.std : corresponding function for ndarrays 

5474 numpy.std : Equivalent function 

5475 """ 

5476 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

5477 

5478 dvar = self.var(axis, dtype, out, ddof, **kwargs) 

5479 if dvar is not masked: 

5480 if out is not None: 

5481 np.power(out, 0.5, out=out, casting='unsafe') 

5482 return out 

5483 dvar = sqrt(dvar) 

5484 return dvar 

5485 

5486 def round(self, decimals=0, out=None): 

5487 """ 

5488 Return each element rounded to the given number of decimals. 

5489 

5490 Refer to `numpy.around` for full documentation. 

5491 

5492 See Also 

5493 -------- 

5494 numpy.ndarray.round : corresponding function for ndarrays 

5495 numpy.around : equivalent function 

5496 """ 

5497 result = self._data.round(decimals=decimals, out=out).view(type(self)) 

5498 if result.ndim > 0: 

5499 result._mask = self._mask 

5500 result._update_from(self) 

5501 elif self._mask: 

5502 # Return masked when the scalar is masked 

5503 result = masked 

5504 # No explicit output: we're done 

5505 if out is None: 

5506 return result 

5507 if isinstance(out, MaskedArray): 

5508 out.__setmask__(self._mask) 

5509 return out 

5510 

5511 def argsort(self, axis=np._NoValue, kind=None, order=None, 

5512 endwith=True, fill_value=None): 

5513 """ 

5514 Return an ndarray of indices that sort the array along the 

5515 specified axis. Masked values are filled beforehand to 

5516 `fill_value`. 

5517 

5518 Parameters 

5519 ---------- 

5520 axis : int, optional 

5521 Axis along which to sort. If None, the default, the flattened array 

5522 is used. 

5523 

5524 .. versionchanged:: 1.13.0 

5525 Previously, the default was documented to be -1, but that was 

5526 in error. At some future date, the default will change to -1, as 

5527 originally intended. 

5528 Until then, the axis should be given explicitly when 

5529 ``arr.ndim > 1``, to avoid a FutureWarning. 

5530 kind : {'quicksort', 'mergesort', 'heapsort', 'stable'}, optional 

5531 The sorting algorithm used. 

5532 order : list, optional 

5533 When `a` is an array with fields defined, this argument specifies 

5534 which fields to compare first, second, etc. Not all fields need be 

5535 specified. 

5536 endwith : {True, False}, optional 

5537 Whether missing values (if any) should be treated as the largest values 

5538 (True) or the smallest values (False) 

5539 When the array contains unmasked values at the same extremes of the 

5540 datatype, the ordering of these values and the masked values is 

5541 undefined. 

5542 fill_value : scalar or None, optional 

5543 Value used internally for the masked values. 

5544 If ``fill_value`` is not None, it supersedes ``endwith``. 

5545 

5546 Returns 

5547 ------- 

5548 index_array : ndarray, int 

5549 Array of indices that sort `a` along the specified axis. 

5550 In other words, ``a[index_array]`` yields a sorted `a`. 

5551 

5552 See Also 

5553 -------- 

5554 ma.MaskedArray.sort : Describes sorting algorithms used. 

5555 lexsort : Indirect stable sort with multiple keys. 

5556 numpy.ndarray.sort : Inplace sort. 

5557 

5558 Notes 

5559 ----- 

5560 See `sort` for notes on the different sorting algorithms. 

5561 

5562 Examples 

5563 -------- 

5564 >>> a = np.ma.array([3,2,1], mask=[False, False, True]) 

5565 >>> a 

5566 masked_array(data=[3, 2, --], 

5567 mask=[False, False, True], 

5568 fill_value=999999) 

5569 >>> a.argsort() 

5570 array([1, 0, 2]) 

5571 

5572 """ 

5573 

5574 # 2017-04-11, Numpy 1.13.0, gh-8701: warn on axis default 

5575 if axis is np._NoValue: 

5576 axis = _deprecate_argsort_axis(self) 

5577 

5578 if fill_value is None: 

5579 if endwith: 

5580 # nan > inf 

5581 if np.issubdtype(self.dtype, np.floating): 

5582 fill_value = np.nan 

5583 else: 

5584 fill_value = minimum_fill_value(self) 

5585 else: 

5586 fill_value = maximum_fill_value(self) 

5587 

5588 filled = self.filled(fill_value) 

5589 return filled.argsort(axis=axis, kind=kind, order=order) 

5590 

5591 def argmin(self, axis=None, fill_value=None, out=None, *, 

5592 keepdims=np._NoValue): 

5593 """ 

5594 Return array of indices to the minimum values along the given axis. 

5595 

5596 Parameters 

5597 ---------- 

5598 axis : {None, integer} 

5599 If None, the index is into the flattened array, otherwise along 

5600 the specified axis 

5601 fill_value : scalar or None, optional 

5602 Value used to fill in the masked values. If None, the output of 

5603 minimum_fill_value(self._data) is used instead. 

5604 out : {None, array}, optional 

5605 Array into which the result can be placed. Its type is preserved 

5606 and it must be of the right shape to hold the output. 

5607 

5608 Returns 

5609 ------- 

5610 ndarray or scalar 

5611 If multi-dimension input, returns a new ndarray of indices to the 

5612 minimum values along the given axis. Otherwise, returns a scalar 

5613 of index to the minimum values along the given axis. 

5614 

5615 Examples 

5616 -------- 

5617 >>> x = np.ma.array(np.arange(4), mask=[1,1,0,0]) 

5618 >>> x.shape = (2,2) 

5619 >>> x 

5620 masked_array( 

5621 data=[[--, --], 

5622 [2, 3]], 

5623 mask=[[ True, True], 

5624 [False, False]], 

5625 fill_value=999999) 

5626 >>> x.argmin(axis=0, fill_value=-1) 

5627 array([0, 0]) 

5628 >>> x.argmin(axis=0, fill_value=9) 

5629 array([1, 1]) 

5630 

5631 """ 

5632 if fill_value is None: 

5633 fill_value = minimum_fill_value(self) 

5634 d = self.filled(fill_value).view(ndarray) 

5635 keepdims = False if keepdims is np._NoValue else bool(keepdims) 

5636 return d.argmin(axis, out=out, keepdims=keepdims) 

5637 

5638 def argmax(self, axis=None, fill_value=None, out=None, *, 

5639 keepdims=np._NoValue): 

5640 """ 

5641 Returns array of indices of the maximum values along the given axis. 

5642 Masked values are treated as if they had the value fill_value. 

5643 

5644 Parameters 

5645 ---------- 

5646 axis : {None, integer} 

5647 If None, the index is into the flattened array, otherwise along 

5648 the specified axis 

5649 fill_value : scalar or None, optional 

5650 Value used to fill in the masked values. If None, the output of 

5651 maximum_fill_value(self._data) is used instead. 

5652 out : {None, array}, optional 

5653 Array into which the result can be placed. Its type is preserved 

5654 and it must be of the right shape to hold the output. 

5655 

5656 Returns 

5657 ------- 

5658 index_array : {integer_array} 

5659 

5660 Examples 

5661 -------- 

5662 >>> a = np.arange(6).reshape(2,3) 

5663 >>> a.argmax() 

5664 5 

5665 >>> a.argmax(0) 

5666 array([1, 1, 1]) 

5667 >>> a.argmax(1) 

5668 array([2, 2]) 

5669 

5670 """ 

5671 if fill_value is None: 

5672 fill_value = maximum_fill_value(self._data) 

5673 d = self.filled(fill_value).view(ndarray) 

5674 keepdims = False if keepdims is np._NoValue else bool(keepdims) 

5675 return d.argmax(axis, out=out, keepdims=keepdims) 

5676 

5677 def sort(self, axis=-1, kind=None, order=None, 

5678 endwith=True, fill_value=None): 

5679 """ 

5680 Sort the array, in-place 

5681 

5682 Parameters 

5683 ---------- 

5684 a : array_like 

5685 Array to be sorted. 

5686 axis : int, optional 

5687 Axis along which to sort. If None, the array is flattened before 

5688 sorting. The default is -1, which sorts along the last axis. 

5689 kind : {'quicksort', 'mergesort', 'heapsort', 'stable'}, optional 

5690 The sorting algorithm used. 

5691 order : list, optional 

5692 When `a` is a structured array, this argument specifies which fields 

5693 to compare first, second, and so on. This list does not need to 

5694 include all of the fields. 

5695 endwith : {True, False}, optional 

5696 Whether missing values (if any) should be treated as the largest values 

5697 (True) or the smallest values (False) 

5698 When the array contains unmasked values sorting at the same extremes of the 

5699 datatype, the ordering of these values and the masked values is 

5700 undefined. 

5701 fill_value : scalar or None, optional 

5702 Value used internally for the masked values. 

5703 If ``fill_value`` is not None, it supersedes ``endwith``. 

5704 

5705 Returns 

5706 ------- 

5707 sorted_array : ndarray 

5708 Array of the same type and shape as `a`. 

5709 

5710 See Also 

5711 -------- 

5712 numpy.ndarray.sort : Method to sort an array in-place. 

5713 argsort : Indirect sort. 

5714 lexsort : Indirect stable sort on multiple keys. 

5715 searchsorted : Find elements in a sorted array. 

5716 

5717 Notes 

5718 ----- 

5719 See ``sort`` for notes on the different sorting algorithms. 

5720 

5721 Examples 

5722 -------- 

5723 >>> a = np.ma.array([1, 2, 5, 4, 3],mask=[0, 1, 0, 1, 0]) 

5724 >>> # Default 

5725 >>> a.sort() 

5726 >>> a 

5727 masked_array(data=[1, 3, 5, --, --], 

5728 mask=[False, False, False, True, True], 

5729 fill_value=999999) 

5730 

5731 >>> a = np.ma.array([1, 2, 5, 4, 3],mask=[0, 1, 0, 1, 0]) 

5732 >>> # Put missing values in the front 

5733 >>> a.sort(endwith=False) 

5734 >>> a 

5735 masked_array(data=[--, --, 1, 3, 5], 

5736 mask=[ True, True, False, False, False], 

5737 fill_value=999999) 

5738 

5739 >>> a = np.ma.array([1, 2, 5, 4, 3],mask=[0, 1, 0, 1, 0]) 

5740 >>> # fill_value takes over endwith 

5741 >>> a.sort(endwith=False, fill_value=3) 

5742 >>> a 

5743 masked_array(data=[1, --, --, 3, 5], 

5744 mask=[False, True, True, False, False], 

5745 fill_value=999999) 

5746 

5747 """ 

5748 if self._mask is nomask: 

5749 ndarray.sort(self, axis=axis, kind=kind, order=order) 

5750 return 

5751 

5752 if self is masked: 

5753 return 

5754 

5755 sidx = self.argsort(axis=axis, kind=kind, order=order, 

5756 fill_value=fill_value, endwith=endwith) 

5757 

5758 self[...] = np.take_along_axis(self, sidx, axis=axis) 

5759 

5760 def min(self, axis=None, out=None, fill_value=None, keepdims=np._NoValue): 

5761 """ 

5762 Return the minimum along a given axis. 

5763 

5764 Parameters 

5765 ---------- 

5766 axis : None or int or tuple of ints, optional 

5767 Axis along which to operate. By default, ``axis`` is None and the 

5768 flattened input is used. 

5769 .. versionadded:: 1.7.0 

5770 If this is a tuple of ints, the minimum is selected over multiple 

5771 axes, instead of a single axis or all the axes as before. 

5772 out : array_like, optional 

5773 Alternative output array in which to place the result. Must be of 

5774 the same shape and buffer length as the expected output. 

5775 fill_value : scalar or None, optional 

5776 Value used to fill in the masked values. 

5777 If None, use the output of `minimum_fill_value`. 

5778 keepdims : bool, optional 

5779 If this is set to True, the axes which are reduced are left 

5780 in the result as dimensions with size one. With this option, 

5781 the result will broadcast correctly against the array. 

5782 

5783 Returns 

5784 ------- 

5785 amin : array_like 

5786 New array holding the result. 

5787 If ``out`` was specified, ``out`` is returned. 

5788 

5789 See Also 

5790 -------- 

5791 ma.minimum_fill_value 

5792 Returns the minimum filling value for a given datatype. 

5793 

5794 Examples 

5795 -------- 

5796 >>> import numpy.ma as ma 

5797 >>> x = [[1., -2., 3.], [0.2, -0.7, 0.1]] 

5798 >>> mask = [[1, 1, 0], [0, 0, 1]] 

5799 >>> masked_x = ma.masked_array(x, mask) 

5800 >>> masked_x 

5801 masked_array( 

5802 data=[[--, --, 3.0], 

5803 [0.2, -0.7, --]], 

5804 mask=[[ True, True, False], 

5805 [False, False, True]], 

5806 fill_value=1e+20) 

5807 >>> ma.min(masked_x) 

5808 -0.7 

5809 >>> ma.min(masked_x, axis=-1) 

5810 masked_array(data=[3.0, -0.7], 

5811 mask=[False, False], 

5812 fill_value=1e+20) 

5813 >>> ma.min(masked_x, axis=0, keepdims=True) 

5814 masked_array(data=[[0.2, -0.7, 3.0]], 

5815 mask=[[False, False, False]], 

5816 fill_value=1e+20) 

5817 >>> mask = [[1, 1, 1,], [1, 1, 1]] 

5818 >>> masked_x = ma.masked_array(x, mask) 

5819 >>> ma.min(masked_x, axis=0) 

5820 masked_array(data=[--, --, --], 

5821 mask=[ True, True, True], 

5822 fill_value=1e+20, 

5823 dtype=float64) 

5824 """ 

5825 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

5826 

5827 _mask = self._mask 

5828 newmask = _check_mask_axis(_mask, axis, **kwargs) 

5829 if fill_value is None: 

5830 fill_value = minimum_fill_value(self) 

5831 # No explicit output 

5832 if out is None: 

5833 result = self.filled(fill_value).min( 

5834 axis=axis, out=out, **kwargs).view(type(self)) 

5835 if result.ndim: 

5836 # Set the mask 

5837 result.__setmask__(newmask) 

5838 # Get rid of Infs 

5839 if newmask.ndim: 

5840 np.copyto(result, result.fill_value, where=newmask) 

5841 elif newmask: 

5842 result = masked 

5843 return result 

5844 # Explicit output 

5845 result = self.filled(fill_value).min(axis=axis, out=out, **kwargs) 

5846 if isinstance(out, MaskedArray): 

5847 outmask = getmask(out) 

5848 if outmask is nomask: 

5849 outmask = out._mask = make_mask_none(out.shape) 

5850 outmask.flat = newmask 

5851 else: 

5852 if out.dtype.kind in 'biu': 

5853 errmsg = "Masked data information would be lost in one or more"\ 

5854 " location." 

5855 raise MaskError(errmsg) 

5856 np.copyto(out, np.nan, where=newmask) 

5857 return out 

5858 

5859 def max(self, axis=None, out=None, fill_value=None, keepdims=np._NoValue): 

5860 """ 

5861 Return the maximum along a given axis. 

5862 

5863 Parameters 

5864 ---------- 

5865 axis : None or int or tuple of ints, optional 

5866 Axis along which to operate. By default, ``axis`` is None and the 

5867 flattened input is used. 

5868 .. versionadded:: 1.7.0 

5869 If this is a tuple of ints, the maximum is selected over multiple 

5870 axes, instead of a single axis or all the axes as before. 

5871 out : array_like, optional 

5872 Alternative output array in which to place the result. Must 

5873 be of the same shape and buffer length as the expected output. 

5874 fill_value : scalar or None, optional 

5875 Value used to fill in the masked values. 

5876 If None, use the output of maximum_fill_value(). 

5877 keepdims : bool, optional 

5878 If this is set to True, the axes which are reduced are left 

5879 in the result as dimensions with size one. With this option, 

5880 the result will broadcast correctly against the array. 

5881 

5882 Returns 

5883 ------- 

5884 amax : array_like 

5885 New array holding the result. 

5886 If ``out`` was specified, ``out`` is returned. 

5887 

5888 See Also 

5889 -------- 

5890 ma.maximum_fill_value 

5891 Returns the maximum filling value for a given datatype. 

5892 

5893 Examples 

5894 -------- 

5895 >>> import numpy.ma as ma 

5896 >>> x = [[-1., 2.5], [4., -2.], [3., 0.]] 

5897 >>> mask = [[0, 0], [1, 0], [1, 0]] 

5898 >>> masked_x = ma.masked_array(x, mask) 

5899 >>> masked_x 

5900 masked_array( 

5901 data=[[-1.0, 2.5], 

5902 [--, -2.0], 

5903 [--, 0.0]], 

5904 mask=[[False, False], 

5905 [ True, False], 

5906 [ True, False]], 

5907 fill_value=1e+20) 

5908 >>> ma.max(masked_x) 

5909 2.5 

5910 >>> ma.max(masked_x, axis=0) 

5911 masked_array(data=[-1.0, 2.5], 

5912 mask=[False, False], 

5913 fill_value=1e+20) 

5914 >>> ma.max(masked_x, axis=1, keepdims=True) 

5915 masked_array( 

5916 data=[[2.5], 

5917 [-2.0], 

5918 [0.0]], 

5919 mask=[[False], 

5920 [False], 

5921 [False]], 

5922 fill_value=1e+20) 

5923 >>> mask = [[1, 1], [1, 1], [1, 1]] 

5924 >>> masked_x = ma.masked_array(x, mask) 

5925 >>> ma.max(masked_x, axis=1) 

5926 masked_array(data=[--, --, --], 

5927 mask=[ True, True, True], 

5928 fill_value=1e+20, 

5929 dtype=float64) 

5930 """ 

5931 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

5932 

5933 _mask = self._mask 

5934 newmask = _check_mask_axis(_mask, axis, **kwargs) 

5935 if fill_value is None: 

5936 fill_value = maximum_fill_value(self) 

5937 # No explicit output 

5938 if out is None: 

5939 result = self.filled(fill_value).max( 

5940 axis=axis, out=out, **kwargs).view(type(self)) 

5941 if result.ndim: 

5942 # Set the mask 

5943 result.__setmask__(newmask) 

5944 # Get rid of Infs 

5945 if newmask.ndim: 

5946 np.copyto(result, result.fill_value, where=newmask) 

5947 elif newmask: 

5948 result = masked 

5949 return result 

5950 # Explicit output 

5951 result = self.filled(fill_value).max(axis=axis, out=out, **kwargs) 

5952 if isinstance(out, MaskedArray): 

5953 outmask = getmask(out) 

5954 if outmask is nomask: 

5955 outmask = out._mask = make_mask_none(out.shape) 

5956 outmask.flat = newmask 

5957 else: 

5958 

5959 if out.dtype.kind in 'biu': 

5960 errmsg = "Masked data information would be lost in one or more"\ 

5961 " location." 

5962 raise MaskError(errmsg) 

5963 np.copyto(out, np.nan, where=newmask) 

5964 return out 

5965 

5966 def ptp(self, axis=None, out=None, fill_value=None, keepdims=False): 

5967 """ 

5968 Return (maximum - minimum) along the given dimension 

5969 (i.e. peak-to-peak value). 

5970 

5971 .. warning:: 

5972 `ptp` preserves the data type of the array. This means the 

5973 return value for an input of signed integers with n bits 

5974 (e.g. `np.int8`, `np.int16`, etc) is also a signed integer 

5975 with n bits. In that case, peak-to-peak values greater than 

5976 ``2**(n-1)-1`` will be returned as negative values. An example 

5977 with a work-around is shown below. 

5978 

5979 Parameters 

5980 ---------- 

5981 axis : {None, int}, optional 

5982 Axis along which to find the peaks. If None (default) the 

5983 flattened array is used. 

5984 out : {None, array_like}, optional 

5985 Alternative output array in which to place the result. It must 

5986 have the same shape and buffer length as the expected output 

5987 but the type will be cast if necessary. 

5988 fill_value : scalar or None, optional 

5989 Value used to fill in the masked values. 

5990 keepdims : bool, optional 

5991 If this is set to True, the axes which are reduced are left 

5992 in the result as dimensions with size one. With this option, 

5993 the result will broadcast correctly against the array. 

5994 

5995 Returns 

5996 ------- 

5997 ptp : ndarray. 

5998 A new array holding the result, unless ``out`` was 

5999 specified, in which case a reference to ``out`` is returned. 

6000 

6001 Examples 

6002 -------- 

6003 >>> x = np.ma.MaskedArray([[4, 9, 2, 10], 

6004 ... [6, 9, 7, 12]]) 

6005 

6006 >>> x.ptp(axis=1) 

6007 masked_array(data=[8, 6], 

6008 mask=False, 

6009 fill_value=999999) 

6010 

6011 >>> x.ptp(axis=0) 

6012 masked_array(data=[2, 0, 5, 2], 

6013 mask=False, 

6014 fill_value=999999) 

6015 

6016 >>> x.ptp() 

6017 10 

6018 

6019 This example shows that a negative value can be returned when 

6020 the input is an array of signed integers. 

6021 

6022 >>> y = np.ma.MaskedArray([[1, 127], 

6023 ... [0, 127], 

6024 ... [-1, 127], 

6025 ... [-2, 127]], dtype=np.int8) 

6026 >>> y.ptp(axis=1) 

6027 masked_array(data=[ 126, 127, -128, -127], 

6028 mask=False, 

6029 fill_value=999999, 

6030 dtype=int8) 

6031 

6032 A work-around is to use the `view()` method to view the result as 

6033 unsigned integers with the same bit width: 

6034 

6035 >>> y.ptp(axis=1).view(np.uint8) 

6036 masked_array(data=[126, 127, 128, 129], 

6037 mask=False, 

6038 fill_value=999999, 

6039 dtype=uint8) 

6040 """ 

6041 if out is None: 

6042 result = self.max(axis=axis, fill_value=fill_value, 

6043 keepdims=keepdims) 

6044 result -= self.min(axis=axis, fill_value=fill_value, 

6045 keepdims=keepdims) 

6046 return result 

6047 out.flat = self.max(axis=axis, out=out, fill_value=fill_value, 

6048 keepdims=keepdims) 

6049 min_value = self.min(axis=axis, fill_value=fill_value, 

6050 keepdims=keepdims) 

6051 np.subtract(out, min_value, out=out, casting='unsafe') 

6052 return out 

6053 

6054 def partition(self, *args, **kwargs): 

6055 warnings.warn("Warning: 'partition' will ignore the 'mask' " 

6056 f"of the {self.__class__.__name__}.", 

6057 stacklevel=2) 

6058 return super().partition(*args, **kwargs) 

6059 

6060 def argpartition(self, *args, **kwargs): 

6061 warnings.warn("Warning: 'argpartition' will ignore the 'mask' " 

6062 f"of the {self.__class__.__name__}.", 

6063 stacklevel=2) 

6064 return super().argpartition(*args, **kwargs) 

6065 

6066 def take(self, indices, axis=None, out=None, mode='raise'): 

6067 """ 

6068 """ 

6069 (_data, _mask) = (self._data, self._mask) 

6070 cls = type(self) 

6071 # Make sure the indices are not masked 

6072 maskindices = getmask(indices) 

6073 if maskindices is not nomask: 

6074 indices = indices.filled(0) 

6075 # Get the data, promoting scalars to 0d arrays with [...] so that 

6076 # .view works correctly 

6077 if out is None: 

6078 out = _data.take(indices, axis=axis, mode=mode)[...].view(cls) 

6079 else: 

6080 np.take(_data, indices, axis=axis, mode=mode, out=out) 

6081 # Get the mask 

6082 if isinstance(out, MaskedArray): 

6083 if _mask is nomask: 

6084 outmask = maskindices 

6085 else: 

6086 outmask = _mask.take(indices, axis=axis, mode=mode) 

6087 outmask |= maskindices 

6088 out.__setmask__(outmask) 

6089 # demote 0d arrays back to scalars, for consistency with ndarray.take 

6090 return out[()] 

6091 

6092 # Array methods 

6093 copy = _arraymethod('copy') 

6094 diagonal = _arraymethod('diagonal') 

6095 flatten = _arraymethod('flatten') 

6096 repeat = _arraymethod('repeat') 

6097 squeeze = _arraymethod('squeeze') 

6098 swapaxes = _arraymethod('swapaxes') 

6099 T = property(fget=lambda self: self.transpose()) 

6100 transpose = _arraymethod('transpose') 

6101 

6102 def tolist(self, fill_value=None): 

6103 """ 

6104 Return the data portion of the masked array as a hierarchical Python list. 

6105 

6106 Data items are converted to the nearest compatible Python type. 

6107 Masked values are converted to `fill_value`. If `fill_value` is None, 

6108 the corresponding entries in the output list will be ``None``. 

6109 

6110 Parameters 

6111 ---------- 

6112 fill_value : scalar, optional 

6113 The value to use for invalid entries. Default is None. 

6114 

6115 Returns 

6116 ------- 

6117 result : list 

6118 The Python list representation of the masked array. 

6119 

6120 Examples 

6121 -------- 

6122 >>> x = np.ma.array([[1,2,3], [4,5,6], [7,8,9]], mask=[0] + [1,0]*4) 

6123 >>> x.tolist() 

6124 [[1, None, 3], [None, 5, None], [7, None, 9]] 

6125 >>> x.tolist(-999) 

6126 [[1, -999, 3], [-999, 5, -999], [7, -999, 9]] 

6127 

6128 """ 

6129 _mask = self._mask 

6130 # No mask ? Just return .data.tolist ? 

6131 if _mask is nomask: 

6132 return self._data.tolist() 

6133 # Explicit fill_value: fill the array and get the list 

6134 if fill_value is not None: 

6135 return self.filled(fill_value).tolist() 

6136 # Structured array. 

6137 names = self.dtype.names 

6138 if names: 

6139 result = self._data.astype([(_, object) for _ in names]) 

6140 for n in names: 

6141 result[n][_mask[n]] = None 

6142 return result.tolist() 

6143 # Standard arrays. 

6144 if _mask is nomask: 

6145 return [None] 

6146 # Set temps to save time when dealing w/ marrays. 

6147 inishape = self.shape 

6148 result = np.array(self._data.ravel(), dtype=object) 

6149 result[_mask.ravel()] = None 

6150 result.shape = inishape 

6151 return result.tolist() 

6152 

6153 def tostring(self, fill_value=None, order='C'): 

6154 r""" 

6155 A compatibility alias for `tobytes`, with exactly the same behavior. 

6156 

6157 Despite its name, it returns `bytes` not `str`\ s. 

6158 

6159 .. deprecated:: 1.19.0 

6160 """ 

6161 # 2020-03-30, Numpy 1.19.0 

6162 warnings.warn( 

6163 "tostring() is deprecated. Use tobytes() instead.", 

6164 DeprecationWarning, stacklevel=2) 

6165 

6166 return self.tobytes(fill_value, order=order) 

6167 

6168 def tobytes(self, fill_value=None, order='C'): 

6169 """ 

6170 Return the array data as a string containing the raw bytes in the array. 

6171 

6172 The array is filled with a fill value before the string conversion. 

6173 

6174 .. versionadded:: 1.9.0 

6175 

6176 Parameters 

6177 ---------- 

6178 fill_value : scalar, optional 

6179 Value used to fill in the masked values. Default is None, in which 

6180 case `MaskedArray.fill_value` is used. 

6181 order : {'C','F','A'}, optional 

6182 Order of the data item in the copy. Default is 'C'. 

6183 

6184 - 'C' -- C order (row major). 

6185 - 'F' -- Fortran order (column major). 

6186 - 'A' -- Any, current order of array. 

6187 - None -- Same as 'A'. 

6188 

6189 See Also 

6190 -------- 

6191 numpy.ndarray.tobytes 

6192 tolist, tofile 

6193 

6194 Notes 

6195 ----- 

6196 As for `ndarray.tobytes`, information about the shape, dtype, etc., 

6197 but also about `fill_value`, will be lost. 

6198 

6199 Examples 

6200 -------- 

6201 >>> x = np.ma.array(np.array([[1, 2], [3, 4]]), mask=[[0, 1], [1, 0]]) 

6202 >>> x.tobytes() 

6203 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' 

6204 

6205 """ 

6206 return self.filled(fill_value).tobytes(order=order) 

6207 

6208 def tofile(self, fid, sep="", format="%s"): 

6209 """ 

6210 Save a masked array to a file in binary format. 

6211 

6212 .. warning:: 

6213 This function is not implemented yet. 

6214 

6215 Raises 

6216 ------ 

6217 NotImplementedError 

6218 When `tofile` is called. 

6219 

6220 """ 

6221 raise NotImplementedError("MaskedArray.tofile() not implemented yet.") 

6222 

6223 def toflex(self): 

6224 """ 

6225 Transforms a masked array into a flexible-type array. 

6226 

6227 The flexible type array that is returned will have two fields: 

6228 

6229 * the ``_data`` field stores the ``_data`` part of the array. 

6230 * the ``_mask`` field stores the ``_mask`` part of the array. 

6231 

6232 Parameters 

6233 ---------- 

6234 None 

6235 

6236 Returns 

6237 ------- 

6238 record : ndarray 

6239 A new flexible-type `ndarray` with two fields: the first element 

6240 containing a value, the second element containing the corresponding 

6241 mask boolean. The returned record shape matches self.shape. 

6242 

6243 Notes 

6244 ----- 

6245 A side-effect of transforming a masked array into a flexible `ndarray` is 

6246 that meta information (``fill_value``, ...) will be lost. 

6247 

6248 Examples 

6249 -------- 

6250 >>> x = np.ma.array([[1,2,3],[4,5,6],[7,8,9]], mask=[0] + [1,0]*4) 

6251 >>> x 

6252 masked_array( 

6253 data=[[1, --, 3], 

6254 [--, 5, --], 

6255 [7, --, 9]], 

6256 mask=[[False, True, False], 

6257 [ True, False, True], 

6258 [False, True, False]], 

6259 fill_value=999999) 

6260 >>> x.toflex() 

6261 array([[(1, False), (2, True), (3, False)], 

6262 [(4, True), (5, False), (6, True)], 

6263 [(7, False), (8, True), (9, False)]], 

6264 dtype=[('_data', '<i8'), ('_mask', '?')]) 

6265 

6266 """ 

6267 # Get the basic dtype. 

6268 ddtype = self.dtype 

6269 # Make sure we have a mask 

6270 _mask = self._mask 

6271 if _mask is None: 

6272 _mask = make_mask_none(self.shape, ddtype) 

6273 # And get its dtype 

6274 mdtype = self._mask.dtype 

6275 

6276 record = np.ndarray(shape=self.shape, 

6277 dtype=[('_data', ddtype), ('_mask', mdtype)]) 

6278 record['_data'] = self._data 

6279 record['_mask'] = self._mask 

6280 return record 

6281 torecords = toflex 

6282 

6283 # Pickling 

6284 def __getstate__(self): 

6285 """Return the internal state of the masked array, for pickling 

6286 purposes. 

6287 

6288 """ 

6289 cf = 'CF'[self.flags.fnc] 

6290 data_state = super().__reduce__()[2] 

6291 return data_state + (getmaskarray(self).tobytes(cf), self._fill_value) 

6292 

6293 def __setstate__(self, state): 

6294 """Restore the internal state of the masked array, for 

6295 pickling purposes. ``state`` is typically the output of the 

6296 ``__getstate__`` output, and is a 5-tuple: 

6297 

6298 - class name 

6299 - a tuple giving the shape of the data 

6300 - a typecode for the data 

6301 - a binary string for the data 

6302 - a binary string for the mask. 

6303 

6304 """ 

6305 (_, shp, typ, isf, raw, msk, flv) = state 

6306 super().__setstate__((shp, typ, isf, raw)) 

6307 self._mask.__setstate__((shp, make_mask_descr(typ), isf, msk)) 

6308 self.fill_value = flv 

6309 

6310 def __reduce__(self): 

6311 """Return a 3-tuple for pickling a MaskedArray. 

6312 

6313 """ 

6314 return (_mareconstruct, 

6315 (self.__class__, self._baseclass, (0,), 'b',), 

6316 self.__getstate__()) 

6317 

6318 def __deepcopy__(self, memo=None): 

6319 from copy import deepcopy 

6320 copied = MaskedArray.__new__(type(self), self, copy=True) 

6321 if memo is None: 

6322 memo = {} 

6323 memo[id(self)] = copied 

6324 for (k, v) in self.__dict__.items(): 

6325 copied.__dict__[k] = deepcopy(v, memo) 

6326 # as clearly documented for np.copy(), you need to use 

6327 # deepcopy() directly for arrays of object type that may 

6328 # contain compound types--you cannot depend on normal 

6329 # copy semantics to do the right thing here 

6330 if self.dtype.hasobject: 

6331 copied._data[...] = deepcopy(copied._data) 

6332 return copied 

6333 

6334 

6335def _mareconstruct(subtype, baseclass, baseshape, basetype,): 

6336 """Internal function that builds a new MaskedArray from the 

6337 information stored in a pickle. 

6338 

6339 """ 

6340 _data = ndarray.__new__(baseclass, baseshape, basetype) 

6341 _mask = ndarray.__new__(ndarray, baseshape, make_mask_descr(basetype)) 

6342 return subtype.__new__(subtype, _data, mask=_mask, dtype=basetype,) 

6343 

6344 

6345class mvoid(MaskedArray): 

6346 """ 

6347 Fake a 'void' object to use for masked array with structured dtypes. 

6348 """ 

6349 

6350 def __new__(self, data, mask=nomask, dtype=None, fill_value=None, 

6351 hardmask=False, copy=False, subok=True): 

6352 _data = np.array(data, copy=copy, subok=subok, dtype=dtype) 

6353 _data = _data.view(self) 

6354 _data._hardmask = hardmask 

6355 if mask is not nomask: 

6356 if isinstance(mask, np.void): 

6357 _data._mask = mask 

6358 else: 

6359 try: 

6360 # Mask is already a 0D array 

6361 _data._mask = np.void(mask) 

6362 except TypeError: 

6363 # Transform the mask to a void 

6364 mdtype = make_mask_descr(dtype) 

6365 _data._mask = np.array(mask, dtype=mdtype)[()] 

6366 if fill_value is not None: 

6367 _data.fill_value = fill_value 

6368 return _data 

6369 

6370 @property 

6371 def _data(self): 

6372 # Make sure that the _data part is a np.void 

6373 return super()._data[()] 

6374 

6375 def __getitem__(self, indx): 

6376 """ 

6377 Get the index. 

6378 

6379 """ 

6380 m = self._mask 

6381 if isinstance(m[indx], ndarray): 

6382 # Can happen when indx is a multi-dimensional field: 

6383 # A = ma.masked_array(data=[([0,1],)], mask=[([True, 

6384 # False],)], dtype=[("A", ">i2", (2,))]) 

6385 # x = A[0]; y = x["A"]; then y.mask["A"].size==2 

6386 # and we can not say masked/unmasked. 

6387 # The result is no longer mvoid! 

6388 # See also issue #6724. 

6389 return masked_array( 

6390 data=self._data[indx], mask=m[indx], 

6391 fill_value=self._fill_value[indx], 

6392 hard_mask=self._hardmask) 

6393 if m is not nomask and m[indx]: 

6394 return masked 

6395 return self._data[indx] 

6396 

6397 def __setitem__(self, indx, value): 

6398 self._data[indx] = value 

6399 if self._hardmask: 

6400 self._mask[indx] |= getattr(value, "_mask", False) 

6401 else: 

6402 self._mask[indx] = getattr(value, "_mask", False) 

6403 

6404 def __str__(self): 

6405 m = self._mask 

6406 if m is nomask: 

6407 return str(self._data) 

6408 

6409 rdtype = _replace_dtype_fields(self._data.dtype, "O") 

6410 data_arr = super()._data 

6411 res = data_arr.astype(rdtype) 

6412 _recursive_printoption(res, self._mask, masked_print_option) 

6413 return str(res) 

6414 

6415 __repr__ = __str__ 

6416 

6417 def __iter__(self): 

6418 "Defines an iterator for mvoid" 

6419 (_data, _mask) = (self._data, self._mask) 

6420 if _mask is nomask: 

6421 yield from _data 

6422 else: 

6423 for (d, m) in zip(_data, _mask): 

6424 if m: 

6425 yield masked 

6426 else: 

6427 yield d 

6428 

6429 def __len__(self): 

6430 return self._data.__len__() 

6431 

6432 def filled(self, fill_value=None): 

6433 """ 

6434 Return a copy with masked fields filled with a given value. 

6435 

6436 Parameters 

6437 ---------- 

6438 fill_value : array_like, optional 

6439 The value to use for invalid entries. Can be scalar or 

6440 non-scalar. If latter is the case, the filled array should 

6441 be broadcastable over input array. Default is None, in 

6442 which case the `fill_value` attribute is used instead. 

6443 

6444 Returns 

6445 ------- 

6446 filled_void 

6447 A `np.void` object 

6448 

6449 See Also 

6450 -------- 

6451 MaskedArray.filled 

6452 

6453 """ 

6454 return asarray(self).filled(fill_value)[()] 

6455 

6456 def tolist(self): 

6457 """ 

6458 Transforms the mvoid object into a tuple. 

6459 

6460 Masked fields are replaced by None. 

6461 

6462 Returns 

6463 ------- 

6464 returned_tuple 

6465 Tuple of fields 

6466 """ 

6467 _mask = self._mask 

6468 if _mask is nomask: 

6469 return self._data.tolist() 

6470 result = [] 

6471 for (d, m) in zip(self._data, self._mask): 

6472 if m: 

6473 result.append(None) 

6474 else: 

6475 # .item() makes sure we return a standard Python object 

6476 result.append(d.item()) 

6477 return tuple(result) 

6478 

6479 

6480############################################################################## 

6481# Shortcuts # 

6482############################################################################## 

6483 

6484 

6485def isMaskedArray(x): 

6486 """ 

6487 Test whether input is an instance of MaskedArray. 

6488 

6489 This function returns True if `x` is an instance of MaskedArray 

6490 and returns False otherwise. Any object is accepted as input. 

6491 

6492 Parameters 

6493 ---------- 

6494 x : object 

6495 Object to test. 

6496 

6497 Returns 

6498 ------- 

6499 result : bool 

6500 True if `x` is a MaskedArray. 

6501 

6502 See Also 

6503 -------- 

6504 isMA : Alias to isMaskedArray. 

6505 isarray : Alias to isMaskedArray. 

6506 

6507 Examples 

6508 -------- 

6509 >>> import numpy.ma as ma 

6510 >>> a = np.eye(3, 3) 

6511 >>> a 

6512 array([[ 1., 0., 0.], 

6513 [ 0., 1., 0.], 

6514 [ 0., 0., 1.]]) 

6515 >>> m = ma.masked_values(a, 0) 

6516 >>> m 

6517 masked_array( 

6518 data=[[1.0, --, --], 

6519 [--, 1.0, --], 

6520 [--, --, 1.0]], 

6521 mask=[[False, True, True], 

6522 [ True, False, True], 

6523 [ True, True, False]], 

6524 fill_value=0.0) 

6525 >>> ma.isMaskedArray(a) 

6526 False 

6527 >>> ma.isMaskedArray(m) 

6528 True 

6529 >>> ma.isMaskedArray([0, 1, 2]) 

6530 False 

6531 

6532 """ 

6533 return isinstance(x, MaskedArray) 

6534 

6535 

6536isarray = isMaskedArray 

6537isMA = isMaskedArray # backward compatibility 

6538 

6539 

6540class MaskedConstant(MaskedArray): 

6541 # the lone np.ma.masked instance 

6542 __singleton = None 

6543 

6544 @classmethod 

6545 def __has_singleton(cls): 

6546 # second case ensures `cls.__singleton` is not just a view on the 

6547 # superclass singleton 

6548 return cls.__singleton is not None and type(cls.__singleton) is cls 

6549 

6550 def __new__(cls): 

6551 if not cls.__has_singleton(): 

6552 # We define the masked singleton as a float for higher precedence. 

6553 # Note that it can be tricky sometimes w/ type comparison 

6554 data = np.array(0.) 

6555 mask = np.array(True) 

6556 

6557 # prevent any modifications 

6558 data.flags.writeable = False 

6559 mask.flags.writeable = False 

6560 

6561 # don't fall back on MaskedArray.__new__(MaskedConstant), since 

6562 # that might confuse it - this way, the construction is entirely 

6563 # within our control 

6564 cls.__singleton = MaskedArray(data, mask=mask).view(cls) 

6565 

6566 return cls.__singleton 

6567 

6568 def __array_finalize__(self, obj): 

6569 if not self.__has_singleton(): 

6570 # this handles the `.view` in __new__, which we want to copy across 

6571 # properties normally 

6572 return super().__array_finalize__(obj) 

6573 elif self is self.__singleton: 

6574 # not clear how this can happen, play it safe 

6575 pass 

6576 else: 

6577 # everywhere else, we want to downcast to MaskedArray, to prevent a 

6578 # duplicate maskedconstant. 

6579 self.__class__ = MaskedArray 

6580 MaskedArray.__array_finalize__(self, obj) 

6581 

6582 def __array_prepare__(self, obj, context=None): 

6583 return self.view(MaskedArray).__array_prepare__(obj, context) 

6584 

6585 def __array_wrap__(self, obj, context=None): 

6586 return self.view(MaskedArray).__array_wrap__(obj, context) 

6587 

6588 def __str__(self): 

6589 return str(masked_print_option._display) 

6590 

6591 def __repr__(self): 

6592 if self is MaskedConstant.__singleton: 

6593 return 'masked' 

6594 else: 

6595 # it's a subclass, or something is wrong, make it obvious 

6596 return object.__repr__(self) 

6597 

6598 def __format__(self, format_spec): 

6599 # Replace ndarray.__format__ with the default, which supports no format characters. 

6600 # Supporting format characters is unwise here, because we do not know what type 

6601 # the user was expecting - better to not guess. 

6602 try: 

6603 return object.__format__(self, format_spec) 

6604 except TypeError: 

6605 # 2020-03-23, NumPy 1.19.0 

6606 warnings.warn( 

6607 "Format strings passed to MaskedConstant are ignored, but in future may " 

6608 "error or produce different behavior", 

6609 FutureWarning, stacklevel=2 

6610 ) 

6611 return object.__format__(self, "") 

6612 

6613 def __reduce__(self): 

6614 """Override of MaskedArray's __reduce__. 

6615 """ 

6616 return (self.__class__, ()) 

6617 

6618 # inplace operations have no effect. We have to override them to avoid 

6619 # trying to modify the readonly data and mask arrays 

6620 def __iop__(self, other): 

6621 return self 

6622 __iadd__ = \ 

6623 __isub__ = \ 

6624 __imul__ = \ 

6625 __ifloordiv__ = \ 

6626 __itruediv__ = \ 

6627 __ipow__ = \ 

6628 __iop__ 

6629 del __iop__ # don't leave this around 

6630 

6631 def copy(self, *args, **kwargs): 

6632 """ Copy is a no-op on the maskedconstant, as it is a scalar """ 

6633 # maskedconstant is a scalar, so copy doesn't need to copy. There's 

6634 # precedent for this with `np.bool_` scalars. 

6635 return self 

6636 

6637 def __copy__(self): 

6638 return self 

6639 

6640 def __deepcopy__(self, memo): 

6641 return self 

6642 

6643 def __setattr__(self, attr, value): 

6644 if not self.__has_singleton(): 

6645 # allow the singleton to be initialized 

6646 return super().__setattr__(attr, value) 

6647 elif self is self.__singleton: 

6648 raise AttributeError( 

6649 f"attributes of {self!r} are not writeable") 

6650 else: 

6651 # duplicate instance - we can end up here from __array_finalize__, 

6652 # where we set the __class__ attribute 

6653 return super().__setattr__(attr, value) 

6654 

6655 

6656masked = masked_singleton = MaskedConstant() 

6657masked_array = MaskedArray 

6658 

6659 

6660def array(data, dtype=None, copy=False, order=None, 

6661 mask=nomask, fill_value=None, keep_mask=True, 

6662 hard_mask=False, shrink=True, subok=True, ndmin=0): 

6663 """ 

6664 Shortcut to MaskedArray. 

6665 

6666 The options are in a different order for convenience and backwards 

6667 compatibility. 

6668 

6669 """ 

6670 return MaskedArray(data, mask=mask, dtype=dtype, copy=copy, 

6671 subok=subok, keep_mask=keep_mask, 

6672 hard_mask=hard_mask, fill_value=fill_value, 

6673 ndmin=ndmin, shrink=shrink, order=order) 

6674array.__doc__ = masked_array.__doc__ 

6675 

6676 

6677def is_masked(x): 

6678 """ 

6679 Determine whether input has masked values. 

6680 

6681 Accepts any object as input, but always returns False unless the 

6682 input is a MaskedArray containing masked values. 

6683 

6684 Parameters 

6685 ---------- 

6686 x : array_like 

6687 Array to check for masked values. 

6688 

6689 Returns 

6690 ------- 

6691 result : bool 

6692 True if `x` is a MaskedArray with masked values, False otherwise. 

6693 

6694 Examples 

6695 -------- 

6696 >>> import numpy.ma as ma 

6697 >>> x = ma.masked_equal([0, 1, 0, 2, 3], 0) 

6698 >>> x 

6699 masked_array(data=[--, 1, --, 2, 3], 

6700 mask=[ True, False, True, False, False], 

6701 fill_value=0) 

6702 >>> ma.is_masked(x) 

6703 True 

6704 >>> x = ma.masked_equal([0, 1, 0, 2, 3], 42) 

6705 >>> x 

6706 masked_array(data=[0, 1, 0, 2, 3], 

6707 mask=False, 

6708 fill_value=42) 

6709 >>> ma.is_masked(x) 

6710 False 

6711 

6712 Always returns False if `x` isn't a MaskedArray. 

6713 

6714 >>> x = [False, True, False] 

6715 >>> ma.is_masked(x) 

6716 False 

6717 >>> x = 'a string' 

6718 >>> ma.is_masked(x) 

6719 False 

6720 

6721 """ 

6722 m = getmask(x) 

6723 if m is nomask: 

6724 return False 

6725 elif m.any(): 

6726 return True 

6727 return False 

6728 

6729 

6730############################################################################## 

6731# Extrema functions # 

6732############################################################################## 

6733 

6734 

6735class _extrema_operation(_MaskedUFunc): 

6736 """ 

6737 Generic class for maximum/minimum functions. 

6738 

6739 .. note:: 

6740 This is the base class for `_maximum_operation` and 

6741 `_minimum_operation`. 

6742 

6743 """ 

6744 def __init__(self, ufunc, compare, fill_value): 

6745 super().__init__(ufunc) 

6746 self.compare = compare 

6747 self.fill_value_func = fill_value 

6748 

6749 def __call__(self, a, b): 

6750 "Executes the call behavior." 

6751 

6752 return where(self.compare(a, b), a, b) 

6753 

6754 def reduce(self, target, axis=np._NoValue): 

6755 "Reduce target along the given axis." 

6756 target = narray(target, copy=False, subok=True) 

6757 m = getmask(target) 

6758 

6759 if axis is np._NoValue and target.ndim > 1: 

6760 # 2017-05-06, Numpy 1.13.0: warn on axis default 

6761 warnings.warn( 

6762 f"In the future the default for ma.{self.__name__}.reduce will be axis=0, " 

6763 f"not the current None, to match np.{self.__name__}.reduce. " 

6764 "Explicitly pass 0 or None to silence this warning.", 

6765 MaskedArrayFutureWarning, stacklevel=2) 

6766 axis = None 

6767 

6768 if axis is not np._NoValue: 

6769 kwargs = dict(axis=axis) 

6770 else: 

6771 kwargs = dict() 

6772 

6773 if m is nomask: 

6774 t = self.f.reduce(target, **kwargs) 

6775 else: 

6776 target = target.filled( 

6777 self.fill_value_func(target)).view(type(target)) 

6778 t = self.f.reduce(target, **kwargs) 

6779 m = umath.logical_and.reduce(m, **kwargs) 

6780 if hasattr(t, '_mask'): 

6781 t._mask = m 

6782 elif m: 

6783 t = masked 

6784 return t 

6785 

6786 def outer(self, a, b): 

6787 "Return the function applied to the outer product of a and b." 

6788 ma = getmask(a) 

6789 mb = getmask(b) 

6790 if ma is nomask and mb is nomask: 

6791 m = nomask 

6792 else: 

6793 ma = getmaskarray(a) 

6794 mb = getmaskarray(b) 

6795 m = logical_or.outer(ma, mb) 

6796 result = self.f.outer(filled(a), filled(b)) 

6797 if not isinstance(result, MaskedArray): 

6798 result = result.view(MaskedArray) 

6799 result._mask = m 

6800 return result 

6801 

6802def min(obj, axis=None, out=None, fill_value=None, keepdims=np._NoValue): 

6803 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

6804 

6805 try: 

6806 return obj.min(axis=axis, fill_value=fill_value, out=out, **kwargs) 

6807 except (AttributeError, TypeError): 

6808 # If obj doesn't have a min method, or if the method doesn't accept a 

6809 # fill_value argument 

6810 return asanyarray(obj).min(axis=axis, fill_value=fill_value, 

6811 out=out, **kwargs) 

6812min.__doc__ = MaskedArray.min.__doc__ 

6813 

6814def max(obj, axis=None, out=None, fill_value=None, keepdims=np._NoValue): 

6815 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

6816 

6817 try: 

6818 return obj.max(axis=axis, fill_value=fill_value, out=out, **kwargs) 

6819 except (AttributeError, TypeError): 

6820 # If obj doesn't have a max method, or if the method doesn't accept a 

6821 # fill_value argument 

6822 return asanyarray(obj).max(axis=axis, fill_value=fill_value, 

6823 out=out, **kwargs) 

6824max.__doc__ = MaskedArray.max.__doc__ 

6825 

6826 

6827def ptp(obj, axis=None, out=None, fill_value=None, keepdims=np._NoValue): 

6828 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

6829 try: 

6830 return obj.ptp(axis, out=out, fill_value=fill_value, **kwargs) 

6831 except (AttributeError, TypeError): 

6832 # If obj doesn't have a ptp method or if the method doesn't accept 

6833 # a fill_value argument 

6834 return asanyarray(obj).ptp(axis=axis, fill_value=fill_value, 

6835 out=out, **kwargs) 

6836ptp.__doc__ = MaskedArray.ptp.__doc__ 

6837 

6838 

6839############################################################################## 

6840# Definition of functions from the corresponding methods # 

6841############################################################################## 

6842 

6843 

6844class _frommethod: 

6845 """ 

6846 Define functions from existing MaskedArray methods. 

6847 

6848 Parameters 

6849 ---------- 

6850 methodname : str 

6851 Name of the method to transform. 

6852 

6853 """ 

6854 

6855 def __init__(self, methodname, reversed=False): 

6856 self.__name__ = methodname 

6857 self.__doc__ = self.getdoc() 

6858 self.reversed = reversed 

6859 

6860 def getdoc(self): 

6861 "Return the doc of the function (from the doc of the method)." 

6862 meth = getattr(MaskedArray, self.__name__, None) or\ 

6863 getattr(np, self.__name__, None) 

6864 signature = self.__name__ + get_object_signature(meth) 

6865 if meth is not None: 

6866 doc = """ %s\n%s""" % ( 

6867 signature, getattr(meth, '__doc__', None)) 

6868 return doc 

6869 

6870 def __call__(self, a, *args, **params): 

6871 if self.reversed: 

6872 args = list(args) 

6873 a, args[0] = args[0], a 

6874 

6875 marr = asanyarray(a) 

6876 method_name = self.__name__ 

6877 method = getattr(type(marr), method_name, None) 

6878 if method is None: 

6879 # use the corresponding np function 

6880 method = getattr(np, method_name) 

6881 

6882 return method(marr, *args, **params) 

6883 

6884 

6885all = _frommethod('all') 

6886anomalies = anom = _frommethod('anom') 

6887any = _frommethod('any') 

6888compress = _frommethod('compress', reversed=True) 

6889cumprod = _frommethod('cumprod') 

6890cumsum = _frommethod('cumsum') 

6891copy = _frommethod('copy') 

6892diagonal = _frommethod('diagonal') 

6893harden_mask = _frommethod('harden_mask') 

6894ids = _frommethod('ids') 

6895maximum = _extrema_operation(umath.maximum, greater, maximum_fill_value) 

6896mean = _frommethod('mean') 

6897minimum = _extrema_operation(umath.minimum, less, minimum_fill_value) 

6898nonzero = _frommethod('nonzero') 

6899prod = _frommethod('prod') 

6900product = _frommethod('prod') 

6901ravel = _frommethod('ravel') 

6902repeat = _frommethod('repeat') 

6903shrink_mask = _frommethod('shrink_mask') 

6904soften_mask = _frommethod('soften_mask') 

6905std = _frommethod('std') 

6906sum = _frommethod('sum') 

6907swapaxes = _frommethod('swapaxes') 

6908#take = _frommethod('take') 

6909trace = _frommethod('trace') 

6910var = _frommethod('var') 

6911 

6912count = _frommethod('count') 

6913 

6914def take(a, indices, axis=None, out=None, mode='raise'): 

6915 """ 

6916 """ 

6917 a = masked_array(a) 

6918 return a.take(indices, axis=axis, out=out, mode=mode) 

6919 

6920 

6921def power(a, b, third=None): 

6922 """ 

6923 Returns element-wise base array raised to power from second array. 

6924 

6925 This is the masked array version of `numpy.power`. For details see 

6926 `numpy.power`. 

6927 

6928 See Also 

6929 -------- 

6930 numpy.power 

6931 

6932 Notes 

6933 ----- 

6934 The *out* argument to `numpy.power` is not supported, `third` has to be 

6935 None. 

6936 

6937 Examples 

6938 -------- 

6939 >>> import numpy.ma as ma 

6940 >>> x = [11.2, -3.973, 0.801, -1.41] 

6941 >>> mask = [0, 0, 0, 1] 

6942 >>> masked_x = ma.masked_array(x, mask) 

6943 >>> masked_x 

6944 masked_array(data=[11.2, -3.973, 0.801, --], 

6945 mask=[False, False, False, True], 

6946 fill_value=1e+20) 

6947 >>> ma.power(masked_x, 2) 

6948 masked_array(data=[125.43999999999998, 15.784728999999999, 

6949 0.6416010000000001, --], 

6950 mask=[False, False, False, True], 

6951 fill_value=1e+20) 

6952 >>> y = [-0.5, 2, 0, 17] 

6953 >>> masked_y = ma.masked_array(y, mask) 

6954 >>> masked_y 

6955 masked_array(data=[-0.5, 2.0, 0.0, --], 

6956 mask=[False, False, False, True], 

6957 fill_value=1e+20) 

6958 >>> ma.power(masked_x, masked_y) 

6959 masked_array(data=[0.29880715233359845, 15.784728999999999, 1.0, --], 

6960 mask=[False, False, False, True], 

6961 fill_value=1e+20) 

6962 

6963 """ 

6964 if third is not None: 

6965 raise MaskError("3-argument power not supported.") 

6966 # Get the masks 

6967 ma = getmask(a) 

6968 mb = getmask(b) 

6969 m = mask_or(ma, mb) 

6970 # Get the rawdata 

6971 fa = getdata(a) 

6972 fb = getdata(b) 

6973 # Get the type of the result (so that we preserve subclasses) 

6974 if isinstance(a, MaskedArray): 

6975 basetype = type(a) 

6976 else: 

6977 basetype = MaskedArray 

6978 # Get the result and view it as a (subclass of) MaskedArray 

6979 with np.errstate(divide='ignore', invalid='ignore'): 

6980 result = np.where(m, fa, umath.power(fa, fb)).view(basetype) 

6981 result._update_from(a) 

6982 # Find where we're in trouble w/ NaNs and Infs 

6983 invalid = np.logical_not(np.isfinite(result.view(ndarray))) 

6984 # Add the initial mask 

6985 if m is not nomask: 

6986 if not result.ndim: 

6987 return masked 

6988 result._mask = np.logical_or(m, invalid) 

6989 # Fix the invalid parts 

6990 if invalid.any(): 

6991 if not result.ndim: 

6992 return masked 

6993 elif result._mask is nomask: 

6994 result._mask = invalid 

6995 result._data[invalid] = result.fill_value 

6996 return result 

6997 

6998argmin = _frommethod('argmin') 

6999argmax = _frommethod('argmax') 

7000 

7001def argsort(a, axis=np._NoValue, kind=None, order=None, endwith=True, fill_value=None): 

7002 "Function version of the eponymous method." 

7003 a = np.asanyarray(a) 

7004 

7005 # 2017-04-11, Numpy 1.13.0, gh-8701: warn on axis default 

7006 if axis is np._NoValue: 

7007 axis = _deprecate_argsort_axis(a) 

7008 

7009 if isinstance(a, MaskedArray): 

7010 return a.argsort(axis=axis, kind=kind, order=order, 

7011 endwith=endwith, fill_value=fill_value) 

7012 else: 

7013 return a.argsort(axis=axis, kind=kind, order=order) 

7014argsort.__doc__ = MaskedArray.argsort.__doc__ 

7015 

7016def sort(a, axis=-1, kind=None, order=None, endwith=True, fill_value=None): 

7017 """ 

7018 Return a sorted copy of the masked array. 

7019 

7020 Equivalent to creating a copy of the array 

7021 and applying the MaskedArray ``sort()`` method. 

7022 

7023 Refer to ``MaskedArray.sort`` for the full documentation 

7024 

7025 See Also 

7026 -------- 

7027 MaskedArray.sort : equivalent method 

7028 

7029 Examples 

7030 -------- 

7031 >>> import numpy.ma as ma 

7032 >>> x = [11.2, -3.973, 0.801, -1.41] 

7033 >>> mask = [0, 0, 0, 1] 

7034 >>> masked_x = ma.masked_array(x, mask) 

7035 >>> masked_x 

7036 masked_array(data=[11.2, -3.973, 0.801, --], 

7037 mask=[False, False, False, True], 

7038 fill_value=1e+20) 

7039 >>> ma.sort(masked_x) 

7040 masked_array(data=[-3.973, 0.801, 11.2, --], 

7041 mask=[False, False, False, True], 

7042 fill_value=1e+20) 

7043 """ 

7044 a = np.array(a, copy=True, subok=True) 

7045 if axis is None: 

7046 a = a.flatten() 

7047 axis = 0 

7048 

7049 if isinstance(a, MaskedArray): 

7050 a.sort(axis=axis, kind=kind, order=order, 

7051 endwith=endwith, fill_value=fill_value) 

7052 else: 

7053 a.sort(axis=axis, kind=kind, order=order) 

7054 return a 

7055 

7056 

7057def compressed(x): 

7058 """ 

7059 Return all the non-masked data as a 1-D array. 

7060 

7061 This function is equivalent to calling the "compressed" method of a 

7062 `ma.MaskedArray`, see `ma.MaskedArray.compressed` for details. 

7063 

7064 See Also 

7065 -------- 

7066 ma.MaskedArray.compressed : Equivalent method. 

7067 

7068 Examples 

7069 -------- 

7070  

7071 Create an array with negative values masked: 

7072 

7073 >>> import numpy as np 

7074 >>> x = np.array([[1, -1, 0], [2, -1, 3], [7, 4, -1]]) 

7075 >>> masked_x = np.ma.masked_array(x, mask=x < 0) 

7076 >>> masked_x 

7077 masked_array( 

7078 data=[[1, --, 0], 

7079 [2, --, 3], 

7080 [7, 4, --]], 

7081 mask=[[False, True, False], 

7082 [False, True, False], 

7083 [False, False, True]], 

7084 fill_value=999999) 

7085 

7086 Compress the masked array into a 1-D array of non-masked values: 

7087 

7088 >>> np.ma.compressed(masked_x) 

7089 array([1, 0, 2, 3, 7, 4]) 

7090 

7091 """ 

7092 return asanyarray(x).compressed() 

7093 

7094 

7095def concatenate(arrays, axis=0): 

7096 """ 

7097 Concatenate a sequence of arrays along the given axis. 

7098 

7099 Parameters 

7100 ---------- 

7101 arrays : sequence of array_like 

7102 The arrays must have the same shape, except in the dimension 

7103 corresponding to `axis` (the first, by default). 

7104 axis : int, optional 

7105 The axis along which the arrays will be joined. Default is 0. 

7106 

7107 Returns 

7108 ------- 

7109 result : MaskedArray 

7110 The concatenated array with any masked entries preserved. 

7111 

7112 See Also 

7113 -------- 

7114 numpy.concatenate : Equivalent function in the top-level NumPy module. 

7115 

7116 Examples 

7117 -------- 

7118 >>> import numpy.ma as ma 

7119 >>> a = ma.arange(3) 

7120 >>> a[1] = ma.masked 

7121 >>> b = ma.arange(2, 5) 

7122 >>> a 

7123 masked_array(data=[0, --, 2], 

7124 mask=[False, True, False], 

7125 fill_value=999999) 

7126 >>> b 

7127 masked_array(data=[2, 3, 4], 

7128 mask=False, 

7129 fill_value=999999) 

7130 >>> ma.concatenate([a, b]) 

7131 masked_array(data=[0, --, 2, 2, 3, 4], 

7132 mask=[False, True, False, False, False, False], 

7133 fill_value=999999) 

7134 

7135 """ 

7136 d = np.concatenate([getdata(a) for a in arrays], axis) 

7137 rcls = get_masked_subclass(*arrays) 

7138 data = d.view(rcls) 

7139 # Check whether one of the arrays has a non-empty mask. 

7140 for x in arrays: 

7141 if getmask(x) is not nomask: 

7142 break 

7143 else: 

7144 return data 

7145 # OK, so we have to concatenate the masks 

7146 dm = np.concatenate([getmaskarray(a) for a in arrays], axis) 

7147 dm = dm.reshape(d.shape) 

7148 

7149 # If we decide to keep a '_shrinkmask' option, we want to check that 

7150 # all of them are True, and then check for dm.any() 

7151 data._mask = _shrink_mask(dm) 

7152 return data 

7153 

7154 

7155def diag(v, k=0): 

7156 """ 

7157 Extract a diagonal or construct a diagonal array. 

7158 

7159 This function is the equivalent of `numpy.diag` that takes masked 

7160 values into account, see `numpy.diag` for details. 

7161 

7162 See Also 

7163 -------- 

7164 numpy.diag : Equivalent function for ndarrays. 

7165 

7166 Examples 

7167 -------- 

7168 

7169 Create an array with negative values masked: 

7170 

7171 >>> import numpy as np 

7172 >>> x = np.array([[11.2, -3.973, 18], [0.801, -1.41, 12], [7, 33, -12]]) 

7173 >>> masked_x = np.ma.masked_array(x, mask=x < 0) 

7174 >>> masked_x 

7175 masked_array( 

7176 data=[[11.2, --, 18.0], 

7177 [0.801, --, 12.0], 

7178 [7.0, 33.0, --]], 

7179 mask=[[False, True, False], 

7180 [False, True, False], 

7181 [False, False, True]], 

7182 fill_value=1e+20) 

7183 

7184 Isolate the main diagonal from the masked array: 

7185 

7186 >>> np.ma.diag(masked_x) 

7187 masked_array(data=[11.2, --, --], 

7188 mask=[False, True, True], 

7189 fill_value=1e+20) 

7190 

7191 Isolate the first diagonal below the main diagonal: 

7192 

7193 >>> np.ma.diag(masked_x, -1) 

7194 masked_array(data=[0.801, 33.0], 

7195 mask=[False, False], 

7196 fill_value=1e+20) 

7197 

7198 """ 

7199 output = np.diag(v, k).view(MaskedArray) 

7200 if getmask(v) is not nomask: 

7201 output._mask = np.diag(v._mask, k) 

7202 return output 

7203 

7204 

7205def left_shift(a, n): 

7206 """ 

7207 Shift the bits of an integer to the left. 

7208 

7209 This is the masked array version of `numpy.left_shift`, for details 

7210 see that function. 

7211 

7212 See Also 

7213 -------- 

7214 numpy.left_shift 

7215 

7216 """ 

7217 m = getmask(a) 

7218 if m is nomask: 

7219 d = umath.left_shift(filled(a), n) 

7220 return masked_array(d) 

7221 else: 

7222 d = umath.left_shift(filled(a, 0), n) 

7223 return masked_array(d, mask=m) 

7224 

7225 

7226def right_shift(a, n): 

7227 """ 

7228 Shift the bits of an integer to the right. 

7229 

7230 This is the masked array version of `numpy.right_shift`, for details 

7231 see that function. 

7232 

7233 See Also 

7234 -------- 

7235 numpy.right_shift 

7236 

7237 Examples 

7238 -------- 

7239 >>> import numpy.ma as ma 

7240 >>> x = [11, 3, 8, 1] 

7241 >>> mask = [0, 0, 0, 1] 

7242 >>> masked_x = ma.masked_array(x, mask) 

7243 >>> masked_x 

7244 masked_array(data=[11, 3, 8, --], 

7245 mask=[False, False, False, True], 

7246 fill_value=999999) 

7247 >>> ma.right_shift(masked_x,1) 

7248 masked_array(data=[5, 1, 4, --], 

7249 mask=[False, False, False, True], 

7250 fill_value=999999) 

7251 

7252 """ 

7253 m = getmask(a) 

7254 if m is nomask: 

7255 d = umath.right_shift(filled(a), n) 

7256 return masked_array(d) 

7257 else: 

7258 d = umath.right_shift(filled(a, 0), n) 

7259 return masked_array(d, mask=m) 

7260 

7261 

7262def put(a, indices, values, mode='raise'): 

7263 """ 

7264 Set storage-indexed locations to corresponding values. 

7265 

7266 This function is equivalent to `MaskedArray.put`, see that method 

7267 for details. 

7268 

7269 See Also 

7270 -------- 

7271 MaskedArray.put 

7272 

7273 """ 

7274 # We can't use 'frommethod', the order of arguments is different 

7275 try: 

7276 return a.put(indices, values, mode=mode) 

7277 except AttributeError: 

7278 return narray(a, copy=False).put(indices, values, mode=mode) 

7279 

7280 

7281def putmask(a, mask, values): # , mode='raise'): 

7282 """ 

7283 Changes elements of an array based on conditional and input values. 

7284 

7285 This is the masked array version of `numpy.putmask`, for details see 

7286 `numpy.putmask`. 

7287 

7288 See Also 

7289 -------- 

7290 numpy.putmask 

7291 

7292 Notes 

7293 ----- 

7294 Using a masked array as `values` will **not** transform a `ndarray` into 

7295 a `MaskedArray`. 

7296 

7297 """ 

7298 # We can't use 'frommethod', the order of arguments is different 

7299 if not isinstance(a, MaskedArray): 

7300 a = a.view(MaskedArray) 

7301 (valdata, valmask) = (getdata(values), getmask(values)) 

7302 if getmask(a) is nomask: 

7303 if valmask is not nomask: 

7304 a._sharedmask = True 

7305 a._mask = make_mask_none(a.shape, a.dtype) 

7306 np.copyto(a._mask, valmask, where=mask) 

7307 elif a._hardmask: 

7308 if valmask is not nomask: 

7309 m = a._mask.copy() 

7310 np.copyto(m, valmask, where=mask) 

7311 a.mask |= m 

7312 else: 

7313 if valmask is nomask: 

7314 valmask = getmaskarray(values) 

7315 np.copyto(a._mask, valmask, where=mask) 

7316 np.copyto(a._data, valdata, where=mask) 

7317 return 

7318 

7319 

7320def transpose(a, axes=None): 

7321 """ 

7322 Permute the dimensions of an array. 

7323 

7324 This function is exactly equivalent to `numpy.transpose`. 

7325 

7326 See Also 

7327 -------- 

7328 numpy.transpose : Equivalent function in top-level NumPy module. 

7329 

7330 Examples 

7331 -------- 

7332 >>> import numpy.ma as ma 

7333 >>> x = ma.arange(4).reshape((2,2)) 

7334 >>> x[1, 1] = ma.masked 

7335 >>> x 

7336 masked_array( 

7337 data=[[0, 1], 

7338 [2, --]], 

7339 mask=[[False, False], 

7340 [False, True]], 

7341 fill_value=999999) 

7342 

7343 >>> ma.transpose(x) 

7344 masked_array( 

7345 data=[[0, 2], 

7346 [1, --]], 

7347 mask=[[False, False], 

7348 [False, True]], 

7349 fill_value=999999) 

7350 """ 

7351 # We can't use 'frommethod', as 'transpose' doesn't take keywords 

7352 try: 

7353 return a.transpose(axes) 

7354 except AttributeError: 

7355 return narray(a, copy=False).transpose(axes).view(MaskedArray) 

7356 

7357 

7358def reshape(a, new_shape, order='C'): 

7359 """ 

7360 Returns an array containing the same data with a new shape. 

7361 

7362 Refer to `MaskedArray.reshape` for full documentation. 

7363 

7364 See Also 

7365 -------- 

7366 MaskedArray.reshape : equivalent function 

7367 

7368 """ 

7369 # We can't use 'frommethod', it whine about some parameters. Dmmit. 

7370 try: 

7371 return a.reshape(new_shape, order=order) 

7372 except AttributeError: 

7373 _tmp = narray(a, copy=False).reshape(new_shape, order=order) 

7374 return _tmp.view(MaskedArray) 

7375 

7376 

7377def resize(x, new_shape): 

7378 """ 

7379 Return a new masked array with the specified size and shape. 

7380 

7381 This is the masked equivalent of the `numpy.resize` function. The new 

7382 array is filled with repeated copies of `x` (in the order that the 

7383 data are stored in memory). If `x` is masked, the new array will be 

7384 masked, and the new mask will be a repetition of the old one. 

7385 

7386 See Also 

7387 -------- 

7388 numpy.resize : Equivalent function in the top level NumPy module. 

7389 

7390 Examples 

7391 -------- 

7392 >>> import numpy.ma as ma 

7393 >>> a = ma.array([[1, 2] ,[3, 4]]) 

7394 >>> a[0, 1] = ma.masked 

7395 >>> a 

7396 masked_array( 

7397 data=[[1, --], 

7398 [3, 4]], 

7399 mask=[[False, True], 

7400 [False, False]], 

7401 fill_value=999999) 

7402 >>> np.resize(a, (3, 3)) 

7403 masked_array( 

7404 data=[[1, 2, 3], 

7405 [4, 1, 2], 

7406 [3, 4, 1]], 

7407 mask=False, 

7408 fill_value=999999) 

7409 >>> ma.resize(a, (3, 3)) 

7410 masked_array( 

7411 data=[[1, --, 3], 

7412 [4, 1, --], 

7413 [3, 4, 1]], 

7414 mask=[[False, True, False], 

7415 [False, False, True], 

7416 [False, False, False]], 

7417 fill_value=999999) 

7418 

7419 A MaskedArray is always returned, regardless of the input type. 

7420 

7421 >>> a = np.array([[1, 2] ,[3, 4]]) 

7422 >>> ma.resize(a, (3, 3)) 

7423 masked_array( 

7424 data=[[1, 2, 3], 

7425 [4, 1, 2], 

7426 [3, 4, 1]], 

7427 mask=False, 

7428 fill_value=999999) 

7429 

7430 """ 

7431 # We can't use _frommethods here, as N.resize is notoriously whiny. 

7432 m = getmask(x) 

7433 if m is not nomask: 

7434 m = np.resize(m, new_shape) 

7435 result = np.resize(x, new_shape).view(get_masked_subclass(x)) 

7436 if result.ndim: 

7437 result._mask = m 

7438 return result 

7439 

7440 

7441def ndim(obj): 

7442 """ 

7443 maskedarray version of the numpy function. 

7444 

7445 """ 

7446 return np.ndim(getdata(obj)) 

7447 

7448ndim.__doc__ = np.ndim.__doc__ 

7449 

7450 

7451def shape(obj): 

7452 "maskedarray version of the numpy function." 

7453 return np.shape(getdata(obj)) 

7454shape.__doc__ = np.shape.__doc__ 

7455 

7456 

7457def size(obj, axis=None): 

7458 "maskedarray version of the numpy function." 

7459 return np.size(getdata(obj), axis) 

7460size.__doc__ = np.size.__doc__ 

7461 

7462 

7463def diff(a, /, n=1, axis=-1, prepend=np._NoValue, append=np._NoValue): 

7464 """ 

7465 Calculate the n-th discrete difference along the given axis. 

7466 The first difference is given by ``out[i] = a[i+1] - a[i]`` along 

7467 the given axis, higher differences are calculated by using `diff` 

7468 recursively. 

7469 Preserves the input mask. 

7470 

7471 Parameters 

7472 ---------- 

7473 a : array_like 

7474 Input array 

7475 n : int, optional 

7476 The number of times values are differenced. If zero, the input 

7477 is returned as-is. 

7478 axis : int, optional 

7479 The axis along which the difference is taken, default is the 

7480 last axis. 

7481 prepend, append : array_like, optional 

7482 Values to prepend or append to `a` along axis prior to 

7483 performing the difference. Scalar values are expanded to 

7484 arrays with length 1 in the direction of axis and the shape 

7485 of the input array in along all other axes. Otherwise the 

7486 dimension and shape must match `a` except along axis. 

7487 

7488 Returns 

7489 ------- 

7490 diff : MaskedArray 

7491 The n-th differences. The shape of the output is the same as `a` 

7492 except along `axis` where the dimension is smaller by `n`. The 

7493 type of the output is the same as the type of the difference 

7494 between any two elements of `a`. This is the same as the type of 

7495 `a` in most cases. A notable exception is `datetime64`, which 

7496 results in a `timedelta64` output array. 

7497 

7498 See Also 

7499 -------- 

7500 numpy.diff : Equivalent function in the top-level NumPy module. 

7501 

7502 Notes 

7503 ----- 

7504 Type is preserved for boolean arrays, so the result will contain 

7505 `False` when consecutive elements are the same and `True` when they 

7506 differ. 

7507 

7508 For unsigned integer arrays, the results will also be unsigned. This 

7509 should not be surprising, as the result is consistent with 

7510 calculating the difference directly: 

7511 

7512 >>> u8_arr = np.array([1, 0], dtype=np.uint8) 

7513 >>> np.ma.diff(u8_arr) 

7514 masked_array(data=[255], 

7515 mask=False, 

7516 fill_value=999999, 

7517 dtype=uint8) 

7518 >>> u8_arr[1,...] - u8_arr[0,...] 

7519 255 

7520 

7521 If this is not desirable, then the array should be cast to a larger 

7522 integer type first: 

7523 

7524 >>> i16_arr = u8_arr.astype(np.int16) 

7525 >>> np.ma.diff(i16_arr) 

7526 masked_array(data=[-1], 

7527 mask=False, 

7528 fill_value=999999, 

7529 dtype=int16) 

7530 

7531 Examples 

7532 -------- 

7533 >>> a = np.array([1, 2, 3, 4, 7, 0, 2, 3]) 

7534 >>> x = np.ma.masked_where(a < 2, a) 

7535 >>> np.ma.diff(x) 

7536 masked_array(data=[--, 1, 1, 3, --, --, 1], 

7537 mask=[ True, False, False, False, True, True, False], 

7538 fill_value=999999) 

7539 

7540 >>> np.ma.diff(x, n=2) 

7541 masked_array(data=[--, 0, 2, --, --, --], 

7542 mask=[ True, False, False, True, True, True], 

7543 fill_value=999999) 

7544 

7545 >>> a = np.array([[1, 3, 1, 5, 10], [0, 1, 5, 6, 8]]) 

7546 >>> x = np.ma.masked_equal(a, value=1) 

7547 >>> np.ma.diff(x) 

7548 masked_array( 

7549 data=[[--, --, --, 5], 

7550 [--, --, 1, 2]], 

7551 mask=[[ True, True, True, False], 

7552 [ True, True, False, False]], 

7553 fill_value=1) 

7554 

7555 >>> np.ma.diff(x, axis=0) 

7556 masked_array(data=[[--, --, --, 1, -2]], 

7557 mask=[[ True, True, True, False, False]], 

7558 fill_value=1) 

7559 

7560 """ 

7561 if n == 0: 

7562 return a 

7563 if n < 0: 

7564 raise ValueError("order must be non-negative but got " + repr(n)) 

7565 

7566 a = np.ma.asanyarray(a) 

7567 if a.ndim == 0: 

7568 raise ValueError( 

7569 "diff requires input that is at least one dimensional" 

7570 ) 

7571 

7572 combined = [] 

7573 if prepend is not np._NoValue: 

7574 prepend = np.ma.asanyarray(prepend) 

7575 if prepend.ndim == 0: 

7576 shape = list(a.shape) 

7577 shape[axis] = 1 

7578 prepend = np.broadcast_to(prepend, tuple(shape)) 

7579 combined.append(prepend) 

7580 

7581 combined.append(a) 

7582 

7583 if append is not np._NoValue: 

7584 append = np.ma.asanyarray(append) 

7585 if append.ndim == 0: 

7586 shape = list(a.shape) 

7587 shape[axis] = 1 

7588 append = np.broadcast_to(append, tuple(shape)) 

7589 combined.append(append) 

7590 

7591 if len(combined) > 1: 

7592 a = np.ma.concatenate(combined, axis) 

7593 

7594 # GH 22465 np.diff without prepend/append preserves the mask 

7595 return np.diff(a, n, axis) 

7596 

7597 

7598############################################################################## 

7599# Extra functions # 

7600############################################################################## 

7601 

7602 

7603def where(condition, x=_NoValue, y=_NoValue): 

7604 """ 

7605 Return a masked array with elements from `x` or `y`, depending on condition. 

7606 

7607 .. note:: 

7608 When only `condition` is provided, this function is identical to 

7609 `nonzero`. The rest of this documentation covers only the case where 

7610 all three arguments are provided. 

7611 

7612 Parameters 

7613 ---------- 

7614 condition : array_like, bool 

7615 Where True, yield `x`, otherwise yield `y`. 

7616 x, y : array_like, optional 

7617 Values from which to choose. `x`, `y` and `condition` need to be 

7618 broadcastable to some shape. 

7619 

7620 Returns 

7621 ------- 

7622 out : MaskedArray 

7623 An masked array with `masked` elements where the condition is masked, 

7624 elements from `x` where `condition` is True, and elements from `y` 

7625 elsewhere. 

7626 

7627 See Also 

7628 -------- 

7629 numpy.where : Equivalent function in the top-level NumPy module. 

7630 nonzero : The function that is called when x and y are omitted 

7631 

7632 Examples 

7633 -------- 

7634 >>> x = np.ma.array(np.arange(9.).reshape(3, 3), mask=[[0, 1, 0], 

7635 ... [1, 0, 1], 

7636 ... [0, 1, 0]]) 

7637 >>> x 

7638 masked_array( 

7639 data=[[0.0, --, 2.0], 

7640 [--, 4.0, --], 

7641 [6.0, --, 8.0]], 

7642 mask=[[False, True, False], 

7643 [ True, False, True], 

7644 [False, True, False]], 

7645 fill_value=1e+20) 

7646 >>> np.ma.where(x > 5, x, -3.1416) 

7647 masked_array( 

7648 data=[[-3.1416, --, -3.1416], 

7649 [--, -3.1416, --], 

7650 [6.0, --, 8.0]], 

7651 mask=[[False, True, False], 

7652 [ True, False, True], 

7653 [False, True, False]], 

7654 fill_value=1e+20) 

7655 

7656 """ 

7657 

7658 # handle the single-argument case 

7659 missing = (x is _NoValue, y is _NoValue).count(True) 

7660 if missing == 1: 

7661 raise ValueError("Must provide both 'x' and 'y' or neither.") 

7662 if missing == 2: 

7663 return nonzero(condition) 

7664 

7665 # we only care if the condition is true - false or masked pick y 

7666 cf = filled(condition, False) 

7667 xd = getdata(x) 

7668 yd = getdata(y) 

7669 

7670 # we need the full arrays here for correct final dimensions 

7671 cm = getmaskarray(condition) 

7672 xm = getmaskarray(x) 

7673 ym = getmaskarray(y) 

7674 

7675 # deal with the fact that masked.dtype == float64, but we don't actually 

7676 # want to treat it as that. 

7677 if x is masked and y is not masked: 

7678 xd = np.zeros((), dtype=yd.dtype) 

7679 xm = np.ones((), dtype=ym.dtype) 

7680 elif y is masked and x is not masked: 

7681 yd = np.zeros((), dtype=xd.dtype) 

7682 ym = np.ones((), dtype=xm.dtype) 

7683 

7684 data = np.where(cf, xd, yd) 

7685 mask = np.where(cf, xm, ym) 

7686 mask = np.where(cm, np.ones((), dtype=mask.dtype), mask) 

7687 

7688 # collapse the mask, for backwards compatibility 

7689 mask = _shrink_mask(mask) 

7690 

7691 return masked_array(data, mask=mask) 

7692 

7693 

7694def choose(indices, choices, out=None, mode='raise'): 

7695 """ 

7696 Use an index array to construct a new array from a list of choices. 

7697 

7698 Given an array of integers and a list of n choice arrays, this method 

7699 will create a new array that merges each of the choice arrays. Where a 

7700 value in `index` is i, the new array will have the value that choices[i] 

7701 contains in the same place. 

7702 

7703 Parameters 

7704 ---------- 

7705 indices : ndarray of ints 

7706 This array must contain integers in ``[0, n-1]``, where n is the 

7707 number of choices. 

7708 choices : sequence of arrays 

7709 Choice arrays. The index array and all of the choices should be 

7710 broadcastable to the same shape. 

7711 out : array, optional 

7712 If provided, the result will be inserted into this array. It should 

7713 be of the appropriate shape and `dtype`. 

7714 mode : {'raise', 'wrap', 'clip'}, optional 

7715 Specifies how out-of-bounds indices will behave. 

7716 

7717 * 'raise' : raise an error 

7718 * 'wrap' : wrap around 

7719 * 'clip' : clip to the range 

7720 

7721 Returns 

7722 ------- 

7723 merged_array : array 

7724 

7725 See Also 

7726 -------- 

7727 choose : equivalent function 

7728 

7729 Examples 

7730 -------- 

7731 >>> choice = np.array([[1,1,1], [2,2,2], [3,3,3]]) 

7732 >>> a = np.array([2, 1, 0]) 

7733 >>> np.ma.choose(a, choice) 

7734 masked_array(data=[3, 2, 1], 

7735 mask=False, 

7736 fill_value=999999) 

7737 

7738 """ 

7739 def fmask(x): 

7740 "Returns the filled array, or True if masked." 

7741 if x is masked: 

7742 return True 

7743 return filled(x) 

7744 

7745 def nmask(x): 

7746 "Returns the mask, True if ``masked``, False if ``nomask``." 

7747 if x is masked: 

7748 return True 

7749 return getmask(x) 

7750 # Get the indices. 

7751 c = filled(indices, 0) 

7752 # Get the masks. 

7753 masks = [nmask(x) for x in choices] 

7754 data = [fmask(x) for x in choices] 

7755 # Construct the mask 

7756 outputmask = np.choose(c, masks, mode=mode) 

7757 outputmask = make_mask(mask_or(outputmask, getmask(indices)), 

7758 copy=False, shrink=True) 

7759 # Get the choices. 

7760 d = np.choose(c, data, mode=mode, out=out).view(MaskedArray) 

7761 if out is not None: 

7762 if isinstance(out, MaskedArray): 

7763 out.__setmask__(outputmask) 

7764 return out 

7765 d.__setmask__(outputmask) 

7766 return d 

7767 

7768 

7769def round_(a, decimals=0, out=None): 

7770 """ 

7771 Return a copy of a, rounded to 'decimals' places. 

7772 

7773 When 'decimals' is negative, it specifies the number of positions 

7774 to the left of the decimal point. The real and imaginary parts of 

7775 complex numbers are rounded separately. Nothing is done if the 

7776 array is not of float type and 'decimals' is greater than or equal 

7777 to 0. 

7778 

7779 Parameters 

7780 ---------- 

7781 decimals : int 

7782 Number of decimals to round to. May be negative. 

7783 out : array_like 

7784 Existing array to use for output. 

7785 If not given, returns a default copy of a. 

7786 

7787 Notes 

7788 ----- 

7789 If out is given and does not have a mask attribute, the mask of a 

7790 is lost! 

7791 

7792 Examples 

7793 -------- 

7794 >>> import numpy.ma as ma 

7795 >>> x = [11.2, -3.973, 0.801, -1.41] 

7796 >>> mask = [0, 0, 0, 1] 

7797 >>> masked_x = ma.masked_array(x, mask) 

7798 >>> masked_x 

7799 masked_array(data=[11.2, -3.973, 0.801, --], 

7800 mask=[False, False, False, True], 

7801 fill_value=1e+20) 

7802 >>> ma.round_(masked_x) 

7803 masked_array(data=[11.0, -4.0, 1.0, --], 

7804 mask=[False, False, False, True], 

7805 fill_value=1e+20) 

7806 >>> ma.round(masked_x, decimals=1) 

7807 masked_array(data=[11.2, -4.0, 0.8, --], 

7808 mask=[False, False, False, True], 

7809 fill_value=1e+20) 

7810 >>> ma.round_(masked_x, decimals=-1) 

7811 masked_array(data=[10.0, -0.0, 0.0, --], 

7812 mask=[False, False, False, True], 

7813 fill_value=1e+20) 

7814 """ 

7815 if out is None: 

7816 return np.round_(a, decimals, out) 

7817 else: 

7818 np.round_(getdata(a), decimals, out) 

7819 if hasattr(out, '_mask'): 

7820 out._mask = getmask(a) 

7821 return out 

7822round = round_ 

7823 

7824 

7825def _mask_propagate(a, axis): 

7826 """ 

7827 Mask whole 1-d vectors of an array that contain masked values. 

7828 """ 

7829 a = array(a, subok=False) 

7830 m = getmask(a) 

7831 if m is nomask or not m.any() or axis is None: 

7832 return a 

7833 a._mask = a._mask.copy() 

7834 axes = normalize_axis_tuple(axis, a.ndim) 

7835 for ax in axes: 

7836 a._mask |= m.any(axis=ax, keepdims=True) 

7837 return a 

7838 

7839 

7840# Include masked dot here to avoid import problems in getting it from 

7841# extras.py. Note that it is not included in __all__, but rather exported 

7842# from extras in order to avoid backward compatibility problems. 

7843def dot(a, b, strict=False, out=None): 

7844 """ 

7845 Return the dot product of two arrays. 

7846 

7847 This function is the equivalent of `numpy.dot` that takes masked values 

7848 into account. Note that `strict` and `out` are in different position 

7849 than in the method version. In order to maintain compatibility with the 

7850 corresponding method, it is recommended that the optional arguments be 

7851 treated as keyword only. At some point that may be mandatory. 

7852 

7853 Parameters 

7854 ---------- 

7855 a, b : masked_array_like 

7856 Inputs arrays. 

7857 strict : bool, optional 

7858 Whether masked data are propagated (True) or set to 0 (False) for 

7859 the computation. Default is False. Propagating the mask means that 

7860 if a masked value appears in a row or column, the whole row or 

7861 column is considered masked. 

7862 out : masked_array, optional 

7863 Output argument. This must have the exact kind that would be returned 

7864 if it was not used. In particular, it must have the right type, must be 

7865 C-contiguous, and its dtype must be the dtype that would be returned 

7866 for `dot(a,b)`. This is a performance feature. Therefore, if these 

7867 conditions are not met, an exception is raised, instead of attempting 

7868 to be flexible. 

7869 

7870 .. versionadded:: 1.10.2 

7871 

7872 See Also 

7873 -------- 

7874 numpy.dot : Equivalent function for ndarrays. 

7875 

7876 Examples 

7877 -------- 

7878 >>> a = np.ma.array([[1, 2, 3], [4, 5, 6]], mask=[[1, 0, 0], [0, 0, 0]]) 

7879 >>> b = np.ma.array([[1, 2], [3, 4], [5, 6]], mask=[[1, 0], [0, 0], [0, 0]]) 

7880 >>> np.ma.dot(a, b) 

7881 masked_array( 

7882 data=[[21, 26], 

7883 [45, 64]], 

7884 mask=[[False, False], 

7885 [False, False]], 

7886 fill_value=999999) 

7887 >>> np.ma.dot(a, b, strict=True) 

7888 masked_array( 

7889 data=[[--, --], 

7890 [--, 64]], 

7891 mask=[[ True, True], 

7892 [ True, False]], 

7893 fill_value=999999) 

7894 

7895 """ 

7896 if strict is True: 

7897 if np.ndim(a) == 0 or np.ndim(b) == 0: 

7898 pass 

7899 elif b.ndim == 1: 

7900 a = _mask_propagate(a, a.ndim - 1) 

7901 b = _mask_propagate(b, b.ndim - 1) 

7902 else: 

7903 a = _mask_propagate(a, a.ndim - 1) 

7904 b = _mask_propagate(b, b.ndim - 2) 

7905 am = ~getmaskarray(a) 

7906 bm = ~getmaskarray(b) 

7907 

7908 if out is None: 

7909 d = np.dot(filled(a, 0), filled(b, 0)) 

7910 m = ~np.dot(am, bm) 

7911 if np.ndim(d) == 0: 

7912 d = np.asarray(d) 

7913 r = d.view(get_masked_subclass(a, b)) 

7914 r.__setmask__(m) 

7915 return r 

7916 else: 

7917 d = np.dot(filled(a, 0), filled(b, 0), out._data) 

7918 if out.mask.shape != d.shape: 

7919 out._mask = np.empty(d.shape, MaskType) 

7920 np.dot(am, bm, out._mask) 

7921 np.logical_not(out._mask, out._mask) 

7922 return out 

7923 

7924 

7925def inner(a, b): 

7926 """ 

7927 Returns the inner product of a and b for arrays of floating point types. 

7928 

7929 Like the generic NumPy equivalent the product sum is over the last dimension 

7930 of a and b. The first argument is not conjugated. 

7931 

7932 """ 

7933 fa = filled(a, 0) 

7934 fb = filled(b, 0) 

7935 if fa.ndim == 0: 

7936 fa.shape = (1,) 

7937 if fb.ndim == 0: 

7938 fb.shape = (1,) 

7939 return np.inner(fa, fb).view(MaskedArray) 

7940inner.__doc__ = doc_note(np.inner.__doc__, 

7941 "Masked values are replaced by 0.") 

7942innerproduct = inner 

7943 

7944 

7945def outer(a, b): 

7946 "maskedarray version of the numpy function." 

7947 fa = filled(a, 0).ravel() 

7948 fb = filled(b, 0).ravel() 

7949 d = np.outer(fa, fb) 

7950 ma = getmask(a) 

7951 mb = getmask(b) 

7952 if ma is nomask and mb is nomask: 

7953 return masked_array(d) 

7954 ma = getmaskarray(a) 

7955 mb = getmaskarray(b) 

7956 m = make_mask(1 - np.outer(1 - ma, 1 - mb), copy=False) 

7957 return masked_array(d, mask=m) 

7958outer.__doc__ = doc_note(np.outer.__doc__, 

7959 "Masked values are replaced by 0.") 

7960outerproduct = outer 

7961 

7962 

7963def _convolve_or_correlate(f, a, v, mode, propagate_mask): 

7964 """ 

7965 Helper function for ma.correlate and ma.convolve 

7966 """ 

7967 if propagate_mask: 

7968 # results which are contributed to by either item in any pair being invalid 

7969 mask = ( 

7970 f(getmaskarray(a), np.ones(np.shape(v), dtype=bool), mode=mode) 

7971 | f(np.ones(np.shape(a), dtype=bool), getmaskarray(v), mode=mode) 

7972 ) 

7973 data = f(getdata(a), getdata(v), mode=mode) 

7974 else: 

7975 # results which are not contributed to by any pair of valid elements 

7976 mask = ~f(~getmaskarray(a), ~getmaskarray(v)) 

7977 data = f(filled(a, 0), filled(v, 0), mode=mode) 

7978 

7979 return masked_array(data, mask=mask) 

7980 

7981 

7982def correlate(a, v, mode='valid', propagate_mask=True): 

7983 """ 

7984 Cross-correlation of two 1-dimensional sequences. 

7985 

7986 Parameters 

7987 ---------- 

7988 a, v : array_like 

7989 Input sequences. 

7990 mode : {'valid', 'same', 'full'}, optional 

7991 Refer to the `np.convolve` docstring. Note that the default 

7992 is 'valid', unlike `convolve`, which uses 'full'. 

7993 propagate_mask : bool 

7994 If True, then a result element is masked if any masked element contributes towards it. 

7995 If False, then a result element is only masked if no non-masked element 

7996 contribute towards it 

7997 

7998 Returns 

7999 ------- 

8000 out : MaskedArray 

8001 Discrete cross-correlation of `a` and `v`. 

8002 

8003 See Also 

8004 -------- 

8005 numpy.correlate : Equivalent function in the top-level NumPy module. 

8006 """ 

8007 return _convolve_or_correlate(np.correlate, a, v, mode, propagate_mask) 

8008 

8009 

8010def convolve(a, v, mode='full', propagate_mask=True): 

8011 """ 

8012 Returns the discrete, linear convolution of two one-dimensional sequences. 

8013 

8014 Parameters 

8015 ---------- 

8016 a, v : array_like 

8017 Input sequences. 

8018 mode : {'valid', 'same', 'full'}, optional 

8019 Refer to the `np.convolve` docstring. 

8020 propagate_mask : bool 

8021 If True, then if any masked element is included in the sum for a result 

8022 element, then the result is masked. 

8023 If False, then the result element is only masked if no non-masked cells 

8024 contribute towards it 

8025 

8026 Returns 

8027 ------- 

8028 out : MaskedArray 

8029 Discrete, linear convolution of `a` and `v`. 

8030 

8031 See Also 

8032 -------- 

8033 numpy.convolve : Equivalent function in the top-level NumPy module. 

8034 """ 

8035 return _convolve_or_correlate(np.convolve, a, v, mode, propagate_mask) 

8036 

8037 

8038def allequal(a, b, fill_value=True): 

8039 """ 

8040 Return True if all entries of a and b are equal, using 

8041 fill_value as a truth value where either or both are masked. 

8042 

8043 Parameters 

8044 ---------- 

8045 a, b : array_like 

8046 Input arrays to compare. 

8047 fill_value : bool, optional 

8048 Whether masked values in a or b are considered equal (True) or not 

8049 (False). 

8050 

8051 Returns 

8052 ------- 

8053 y : bool 

8054 Returns True if the two arrays are equal within the given 

8055 tolerance, False otherwise. If either array contains NaN, 

8056 then False is returned. 

8057 

8058 See Also 

8059 -------- 

8060 all, any 

8061 numpy.ma.allclose 

8062 

8063 Examples 

8064 -------- 

8065 >>> a = np.ma.array([1e10, 1e-7, 42.0], mask=[0, 0, 1]) 

8066 >>> a 

8067 masked_array(data=[10000000000.0, 1e-07, --], 

8068 mask=[False, False, True], 

8069 fill_value=1e+20) 

8070 

8071 >>> b = np.array([1e10, 1e-7, -42.0]) 

8072 >>> b 

8073 array([ 1.00000000e+10, 1.00000000e-07, -4.20000000e+01]) 

8074 >>> np.ma.allequal(a, b, fill_value=False) 

8075 False 

8076 >>> np.ma.allequal(a, b) 

8077 True 

8078 

8079 """ 

8080 m = mask_or(getmask(a), getmask(b)) 

8081 if m is nomask: 

8082 x = getdata(a) 

8083 y = getdata(b) 

8084 d = umath.equal(x, y) 

8085 return d.all() 

8086 elif fill_value: 

8087 x = getdata(a) 

8088 y = getdata(b) 

8089 d = umath.equal(x, y) 

8090 dm = array(d, mask=m, copy=False) 

8091 return dm.filled(True).all(None) 

8092 else: 

8093 return False 

8094 

8095 

8096def allclose(a, b, masked_equal=True, rtol=1e-5, atol=1e-8): 

8097 """ 

8098 Returns True if two arrays are element-wise equal within a tolerance. 

8099 

8100 This function is equivalent to `allclose` except that masked values 

8101 are treated as equal (default) or unequal, depending on the `masked_equal` 

8102 argument. 

8103 

8104 Parameters 

8105 ---------- 

8106 a, b : array_like 

8107 Input arrays to compare. 

8108 masked_equal : bool, optional 

8109 Whether masked values in `a` and `b` are considered equal (True) or not 

8110 (False). They are considered equal by default. 

8111 rtol : float, optional 

8112 Relative tolerance. The relative difference is equal to ``rtol * b``. 

8113 Default is 1e-5. 

8114 atol : float, optional 

8115 Absolute tolerance. The absolute difference is equal to `atol`. 

8116 Default is 1e-8. 

8117 

8118 Returns 

8119 ------- 

8120 y : bool 

8121 Returns True if the two arrays are equal within the given 

8122 tolerance, False otherwise. If either array contains NaN, then 

8123 False is returned. 

8124 

8125 See Also 

8126 -------- 

8127 all, any 

8128 numpy.allclose : the non-masked `allclose`. 

8129 

8130 Notes 

8131 ----- 

8132 If the following equation is element-wise True, then `allclose` returns 

8133 True:: 

8134 

8135 absolute(`a` - `b`) <= (`atol` + `rtol` * absolute(`b`)) 

8136 

8137 Return True if all elements of `a` and `b` are equal subject to 

8138 given tolerances. 

8139 

8140 Examples 

8141 -------- 

8142 >>> a = np.ma.array([1e10, 1e-7, 42.0], mask=[0, 0, 1]) 

8143 >>> a 

8144 masked_array(data=[10000000000.0, 1e-07, --], 

8145 mask=[False, False, True], 

8146 fill_value=1e+20) 

8147 >>> b = np.ma.array([1e10, 1e-8, -42.0], mask=[0, 0, 1]) 

8148 >>> np.ma.allclose(a, b) 

8149 False 

8150 

8151 >>> a = np.ma.array([1e10, 1e-8, 42.0], mask=[0, 0, 1]) 

8152 >>> b = np.ma.array([1.00001e10, 1e-9, -42.0], mask=[0, 0, 1]) 

8153 >>> np.ma.allclose(a, b) 

8154 True 

8155 >>> np.ma.allclose(a, b, masked_equal=False) 

8156 False 

8157 

8158 Masked values are not compared directly. 

8159 

8160 >>> a = np.ma.array([1e10, 1e-8, 42.0], mask=[0, 0, 1]) 

8161 >>> b = np.ma.array([1.00001e10, 1e-9, 42.0], mask=[0, 0, 1]) 

8162 >>> np.ma.allclose(a, b) 

8163 True 

8164 >>> np.ma.allclose(a, b, masked_equal=False) 

8165 False 

8166 

8167 """ 

8168 x = masked_array(a, copy=False) 

8169 y = masked_array(b, copy=False) 

8170 

8171 # make sure y is an inexact type to avoid abs(MIN_INT); will cause 

8172 # casting of x later. 

8173 # NOTE: We explicitly allow timedelta, which used to work. This could 

8174 # possibly be deprecated. See also gh-18286. 

8175 # timedelta works if `atol` is an integer or also a timedelta. 

8176 # Although, the default tolerances are unlikely to be useful 

8177 if y.dtype.kind != "m": 

8178 dtype = np.result_type(y, 1.) 

8179 if y.dtype != dtype: 

8180 y = masked_array(y, dtype=dtype, copy=False) 

8181 

8182 m = mask_or(getmask(x), getmask(y)) 

8183 xinf = np.isinf(masked_array(x, copy=False, mask=m)).filled(False) 

8184 # If we have some infs, they should fall at the same place. 

8185 if not np.all(xinf == filled(np.isinf(y), False)): 

8186 return False 

8187 # No infs at all 

8188 if not np.any(xinf): 

8189 d = filled(less_equal(absolute(x - y), atol + rtol * absolute(y)), 

8190 masked_equal) 

8191 return np.all(d) 

8192 

8193 if not np.all(filled(x[xinf] == y[xinf], masked_equal)): 

8194 return False 

8195 x = x[~xinf] 

8196 y = y[~xinf] 

8197 

8198 d = filled(less_equal(absolute(x - y), atol + rtol * absolute(y)), 

8199 masked_equal) 

8200 

8201 return np.all(d) 

8202 

8203 

8204def asarray(a, dtype=None, order=None): 

8205 """ 

8206 Convert the input to a masked array of the given data-type. 

8207 

8208 No copy is performed if the input is already an `ndarray`. If `a` is 

8209 a subclass of `MaskedArray`, a base class `MaskedArray` is returned. 

8210 

8211 Parameters 

8212 ---------- 

8213 a : array_like 

8214 Input data, in any form that can be converted to a masked array. This 

8215 includes lists, lists of tuples, tuples, tuples of tuples, tuples 

8216 of lists, ndarrays and masked arrays. 

8217 dtype : dtype, optional 

8218 By default, the data-type is inferred from the input data. 

8219 order : {'C', 'F'}, optional 

8220 Whether to use row-major ('C') or column-major ('FORTRAN') memory 

8221 representation. Default is 'C'. 

8222 

8223 Returns 

8224 ------- 

8225 out : MaskedArray 

8226 Masked array interpretation of `a`. 

8227 

8228 See Also 

8229 -------- 

8230 asanyarray : Similar to `asarray`, but conserves subclasses. 

8231 

8232 Examples 

8233 -------- 

8234 >>> x = np.arange(10.).reshape(2, 5) 

8235 >>> x 

8236 array([[0., 1., 2., 3., 4.], 

8237 [5., 6., 7., 8., 9.]]) 

8238 >>> np.ma.asarray(x) 

8239 masked_array( 

8240 data=[[0., 1., 2., 3., 4.], 

8241 [5., 6., 7., 8., 9.]], 

8242 mask=False, 

8243 fill_value=1e+20) 

8244 >>> type(np.ma.asarray(x)) 

8245 <class 'numpy.ma.core.MaskedArray'> 

8246 

8247 """ 

8248 order = order or 'C' 

8249 return masked_array(a, dtype=dtype, copy=False, keep_mask=True, 

8250 subok=False, order=order) 

8251 

8252 

8253def asanyarray(a, dtype=None): 

8254 """ 

8255 Convert the input to a masked array, conserving subclasses. 

8256 

8257 If `a` is a subclass of `MaskedArray`, its class is conserved. 

8258 No copy is performed if the input is already an `ndarray`. 

8259 

8260 Parameters 

8261 ---------- 

8262 a : array_like 

8263 Input data, in any form that can be converted to an array. 

8264 dtype : dtype, optional 

8265 By default, the data-type is inferred from the input data. 

8266 order : {'C', 'F'}, optional 

8267 Whether to use row-major ('C') or column-major ('FORTRAN') memory 

8268 representation. Default is 'C'. 

8269 

8270 Returns 

8271 ------- 

8272 out : MaskedArray 

8273 MaskedArray interpretation of `a`. 

8274 

8275 See Also 

8276 -------- 

8277 asarray : Similar to `asanyarray`, but does not conserve subclass. 

8278 

8279 Examples 

8280 -------- 

8281 >>> x = np.arange(10.).reshape(2, 5) 

8282 >>> x 

8283 array([[0., 1., 2., 3., 4.], 

8284 [5., 6., 7., 8., 9.]]) 

8285 >>> np.ma.asanyarray(x) 

8286 masked_array( 

8287 data=[[0., 1., 2., 3., 4.], 

8288 [5., 6., 7., 8., 9.]], 

8289 mask=False, 

8290 fill_value=1e+20) 

8291 >>> type(np.ma.asanyarray(x)) 

8292 <class 'numpy.ma.core.MaskedArray'> 

8293 

8294 """ 

8295 # workaround for #8666, to preserve identity. Ideally the bottom line 

8296 # would handle this for us. 

8297 if isinstance(a, MaskedArray) and (dtype is None or dtype == a.dtype): 

8298 return a 

8299 return masked_array(a, dtype=dtype, copy=False, keep_mask=True, subok=True) 

8300 

8301 

8302############################################################################## 

8303# Pickling # 

8304############################################################################## 

8305 

8306 

8307def fromfile(file, dtype=float, count=-1, sep=''): 

8308 raise NotImplementedError( 

8309 "fromfile() not yet implemented for a MaskedArray.") 

8310 

8311 

8312def fromflex(fxarray): 

8313 """ 

8314 Build a masked array from a suitable flexible-type array. 

8315 

8316 The input array has to have a data-type with ``_data`` and ``_mask`` 

8317 fields. This type of array is output by `MaskedArray.toflex`. 

8318 

8319 Parameters 

8320 ---------- 

8321 fxarray : ndarray 

8322 The structured input array, containing ``_data`` and ``_mask`` 

8323 fields. If present, other fields are discarded. 

8324 

8325 Returns 

8326 ------- 

8327 result : MaskedArray 

8328 The constructed masked array. 

8329 

8330 See Also 

8331 -------- 

8332 MaskedArray.toflex : Build a flexible-type array from a masked array. 

8333 

8334 Examples 

8335 -------- 

8336 >>> x = np.ma.array(np.arange(9).reshape(3, 3), mask=[0] + [1, 0] * 4) 

8337 >>> rec = x.toflex() 

8338 >>> rec 

8339 array([[(0, False), (1, True), (2, False)], 

8340 [(3, True), (4, False), (5, True)], 

8341 [(6, False), (7, True), (8, False)]], 

8342 dtype=[('_data', '<i8'), ('_mask', '?')]) 

8343 >>> x2 = np.ma.fromflex(rec) 

8344 >>> x2 

8345 masked_array( 

8346 data=[[0, --, 2], 

8347 [--, 4, --], 

8348 [6, --, 8]], 

8349 mask=[[False, True, False], 

8350 [ True, False, True], 

8351 [False, True, False]], 

8352 fill_value=999999) 

8353 

8354 Extra fields can be present in the structured array but are discarded: 

8355 

8356 >>> dt = [('_data', '<i4'), ('_mask', '|b1'), ('field3', '<f4')] 

8357 >>> rec2 = np.zeros((2, 2), dtype=dt) 

8358 >>> rec2 

8359 array([[(0, False, 0.), (0, False, 0.)], 

8360 [(0, False, 0.), (0, False, 0.)]], 

8361 dtype=[('_data', '<i4'), ('_mask', '?'), ('field3', '<f4')]) 

8362 >>> y = np.ma.fromflex(rec2) 

8363 >>> y 

8364 masked_array( 

8365 data=[[0, 0], 

8366 [0, 0]], 

8367 mask=[[False, False], 

8368 [False, False]], 

8369 fill_value=999999, 

8370 dtype=int32) 

8371 

8372 """ 

8373 return masked_array(fxarray['_data'], mask=fxarray['_mask']) 

8374 

8375 

8376class _convert2ma: 

8377 

8378 """ 

8379 Convert functions from numpy to numpy.ma. 

8380 

8381 Parameters 

8382 ---------- 

8383 _methodname : string 

8384 Name of the method to transform. 

8385 

8386 """ 

8387 __doc__ = None 

8388 

8389 def __init__(self, funcname, np_ret, np_ma_ret, params=None): 

8390 self._func = getattr(np, funcname) 

8391 self.__doc__ = self.getdoc(np_ret, np_ma_ret) 

8392 self._extras = params or {} 

8393 

8394 def getdoc(self, np_ret, np_ma_ret): 

8395 "Return the doc of the function (from the doc of the method)." 

8396 doc = getattr(self._func, '__doc__', None) 

8397 sig = get_object_signature(self._func) 

8398 if doc: 

8399 doc = self._replace_return_type(doc, np_ret, np_ma_ret) 

8400 # Add the signature of the function at the beginning of the doc 

8401 if sig: 

8402 sig = "%s%s\n" % (self._func.__name__, sig) 

8403 doc = sig + doc 

8404 return doc 

8405 

8406 def _replace_return_type(self, doc, np_ret, np_ma_ret): 

8407 """ 

8408 Replace documentation of ``np`` function's return type. 

8409 

8410 Replaces it with the proper type for the ``np.ma`` function. 

8411 

8412 Parameters 

8413 ---------- 

8414 doc : str 

8415 The documentation of the ``np`` method. 

8416 np_ret : str 

8417 The return type string of the ``np`` method that we want to 

8418 replace. (e.g. "out : ndarray") 

8419 np_ma_ret : str 

8420 The return type string of the ``np.ma`` method. 

8421 (e.g. "out : MaskedArray") 

8422 """ 

8423 if np_ret not in doc: 

8424 raise RuntimeError( 

8425 f"Failed to replace `{np_ret}` with `{np_ma_ret}`. " 

8426 f"The documentation string for return type, {np_ret}, is not " 

8427 f"found in the docstring for `np.{self._func.__name__}`. " 

8428 f"Fix the docstring for `np.{self._func.__name__}` or " 

8429 "update the expected string for return type." 

8430 ) 

8431 

8432 return doc.replace(np_ret, np_ma_ret) 

8433 

8434 def __call__(self, *args, **params): 

8435 # Find the common parameters to the call and the definition 

8436 _extras = self._extras 

8437 common_params = set(params).intersection(_extras) 

8438 # Drop the common parameters from the call 

8439 for p in common_params: 

8440 _extras[p] = params.pop(p) 

8441 # Get the result 

8442 result = self._func.__call__(*args, **params).view(MaskedArray) 

8443 if "fill_value" in common_params: 

8444 result.fill_value = _extras.get("fill_value", None) 

8445 if "hardmask" in common_params: 

8446 result._hardmask = bool(_extras.get("hard_mask", False)) 

8447 return result 

8448 

8449 

8450arange = _convert2ma( 

8451 'arange', 

8452 params=dict(fill_value=None, hardmask=False), 

8453 np_ret='arange : ndarray', 

8454 np_ma_ret='arange : MaskedArray', 

8455) 

8456clip = _convert2ma( 

8457 'clip', 

8458 params=dict(fill_value=None, hardmask=False), 

8459 np_ret='clipped_array : ndarray', 

8460 np_ma_ret='clipped_array : MaskedArray', 

8461) 

8462empty = _convert2ma( 

8463 'empty', 

8464 params=dict(fill_value=None, hardmask=False), 

8465 np_ret='out : ndarray', 

8466 np_ma_ret='out : MaskedArray', 

8467) 

8468empty_like = _convert2ma( 

8469 'empty_like', 

8470 np_ret='out : ndarray', 

8471 np_ma_ret='out : MaskedArray', 

8472) 

8473frombuffer = _convert2ma( 

8474 'frombuffer', 

8475 np_ret='out : ndarray', 

8476 np_ma_ret='out: MaskedArray', 

8477) 

8478fromfunction = _convert2ma( 

8479 'fromfunction', 

8480 np_ret='fromfunction : any', 

8481 np_ma_ret='fromfunction: MaskedArray', 

8482) 

8483identity = _convert2ma( 

8484 'identity', 

8485 params=dict(fill_value=None, hardmask=False), 

8486 np_ret='out : ndarray', 

8487 np_ma_ret='out : MaskedArray', 

8488) 

8489indices = _convert2ma( 

8490 'indices', 

8491 params=dict(fill_value=None, hardmask=False), 

8492 np_ret='grid : one ndarray or tuple of ndarrays', 

8493 np_ma_ret='grid : one MaskedArray or tuple of MaskedArrays', 

8494) 

8495ones = _convert2ma( 

8496 'ones', 

8497 params=dict(fill_value=None, hardmask=False), 

8498 np_ret='out : ndarray', 

8499 np_ma_ret='out : MaskedArray', 

8500) 

8501ones_like = _convert2ma( 

8502 'ones_like', 

8503 np_ret='out : ndarray', 

8504 np_ma_ret='out : MaskedArray', 

8505) 

8506squeeze = _convert2ma( 

8507 'squeeze', 

8508 params=dict(fill_value=None, hardmask=False), 

8509 np_ret='squeezed : ndarray', 

8510 np_ma_ret='squeezed : MaskedArray', 

8511) 

8512zeros = _convert2ma( 

8513 'zeros', 

8514 params=dict(fill_value=None, hardmask=False), 

8515 np_ret='out : ndarray', 

8516 np_ma_ret='out : MaskedArray', 

8517) 

8518zeros_like = _convert2ma( 

8519 'zeros_like', 

8520 np_ret='out : ndarray', 

8521 np_ma_ret='out : MaskedArray', 

8522) 

8523 

8524 

8525def append(a, b, axis=None): 

8526 """Append values to the end of an array. 

8527 

8528 .. versionadded:: 1.9.0 

8529 

8530 Parameters 

8531 ---------- 

8532 a : array_like 

8533 Values are appended to a copy of this array. 

8534 b : array_like 

8535 These values are appended to a copy of `a`. It must be of the 

8536 correct shape (the same shape as `a`, excluding `axis`). If `axis` 

8537 is not specified, `b` can be any shape and will be flattened 

8538 before use. 

8539 axis : int, optional 

8540 The axis along which `v` are appended. If `axis` is not given, 

8541 both `a` and `b` are flattened before use. 

8542 

8543 Returns 

8544 ------- 

8545 append : MaskedArray 

8546 A copy of `a` with `b` appended to `axis`. Note that `append` 

8547 does not occur in-place: a new array is allocated and filled. If 

8548 `axis` is None, the result is a flattened array. 

8549 

8550 See Also 

8551 -------- 

8552 numpy.append : Equivalent function in the top-level NumPy module. 

8553 

8554 Examples 

8555 -------- 

8556 >>> import numpy.ma as ma 

8557 >>> a = ma.masked_values([1, 2, 3], 2) 

8558 >>> b = ma.masked_values([[4, 5, 6], [7, 8, 9]], 7) 

8559 >>> ma.append(a, b) 

8560 masked_array(data=[1, --, 3, 4, 5, 6, --, 8, 9], 

8561 mask=[False, True, False, False, False, False, True, False, 

8562 False], 

8563 fill_value=999999) 

8564 """ 

8565 return concatenate([a, b], axis)