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

2424 statements  

« prev     ^ index     » next       coverage.py v7.0.5, created at 2023-01-17 06:27 +0000

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: 

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 data._mask.shape = data.shape 

2874 else: 

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

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

2877 

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

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

2880 if mask is None: 

2881 mask = False 

2882 

2883 if mask is True and mdtype == MaskType: 

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

2885 elif mask is False and mdtype == MaskType: 

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

2887 else: 

2888 # Read the mask with the current mdtype 

2889 try: 

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

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

2892 except TypeError: 

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

2894 dtype=mdtype) 

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

2896 if mask.shape != _data.shape: 

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

2898 if nm == 1: 

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

2900 elif nm == nd: 

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

2902 else: 

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

2904 "mask size is %i." 

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

2906 copy = True 

2907 # Set the mask to the new value 

2908 if _data._mask is nomask: 

2909 _data._mask = mask 

2910 _data._sharedmask = not copy 

2911 else: 

2912 if not keep_mask: 

2913 _data._mask = mask 

2914 _data._sharedmask = not copy 

2915 else: 

2916 if _data.dtype.names is not None: 

2917 def _recursive_or(a, b): 

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

2919 for name in a.dtype.names: 

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

2921 if af.dtype.names is not None: 

2922 _recursive_or(af, bf) 

2923 else: 

2924 af |= bf 

2925 

2926 _recursive_or(_data._mask, mask) 

2927 else: 

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

2929 _data._sharedmask = False 

2930 

2931 # Update fill_value. 

2932 if fill_value is None: 

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

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

2935 if fill_value is not None: 

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

2937 # Process extra options .. 

2938 if hard_mask is None: 

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

2940 else: 

2941 _data._hardmask = hard_mask 

2942 _data._baseclass = _baseclass 

2943 return _data 

2944 

2945 

2946 def _update_from(self, obj): 

2947 """ 

2948 Copies some attributes of obj to self. 

2949 

2950 """ 

2951 if isinstance(obj, ndarray): 

2952 _baseclass = type(obj) 

2953 else: 

2954 _baseclass = ndarray 

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

2956 _optinfo = {} 

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

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

2959 if not isinstance(obj, MaskedArray): 

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

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

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

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

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

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

2966 _optinfo=_optinfo, 

2967 _basedict=_optinfo) 

2968 self.__dict__.update(_dict) 

2969 self.__dict__.update(_optinfo) 

2970 return 

2971 

2972 def __array_finalize__(self, obj): 

2973 """ 

2974 Finalizes the masked array. 

2975 

2976 """ 

2977 # Get main attributes. 

2978 self._update_from(obj) 

2979 

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

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

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

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

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

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

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

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

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

2989 # clear consensus about what the desired behavior is. For instance, 

2990 # most users think that np.empty_like(marr) -- which goes via this 

2991 # method -- should return a masked array with an empty mask (see 

2992 # gh-3404 and linked discussions), but others disagree, and they have 

2993 # existing code which depends on empty_like returning an array that 

2994 # matches the input mask. 

2995 # 

2996 # Historically our algorithm was: if the template object mask had the 

2997 # same *number of elements* as us, then we used *it's mask object 

2998 # itself* as our mask, so that writes to us would also write to the 

2999 # original array. This is horribly broken in multiple ways. 

3000 # 

3001 # Now what we do instead is, if the template object mask has the same 

3002 # number of elements as us, and we do not have the same base pointer 

3003 # as the template object (b/c views like arr[...] should keep the same 

3004 # mask), then we make a copy of the template object mask and use 

3005 # that. This is also horribly broken but somewhat less so. Maybe. 

3006 if isinstance(obj, ndarray): 

3007 # XX: This looks like a bug -- shouldn't it check self.dtype 

3008 # instead? 

3009 if obj.dtype.names is not None: 

3010 _mask = getmaskarray(obj) 

3011 else: 

3012 _mask = getmask(obj) 

3013 

3014 # If self and obj point to exactly the same data, then probably 

3015 # self is a simple view of obj (e.g., self = obj[...]), so they 

3016 # should share the same mask. (This isn't 100% reliable, e.g. self 

3017 # could be the first row of obj, or have strange strides, but as a 

3018 # heuristic it's not bad.) In all other cases, we make a copy of 

3019 # the mask, so that future modifications to 'self' do not end up 

3020 # side-effecting 'obj' as well. 

3021 if (_mask is not nomask and obj.__array_interface__["data"][0] 

3022 != self.__array_interface__["data"][0]): 

3023 # We should make a copy. But we could get here via astype, 

3024 # in which case the mask might need a new dtype as well 

3025 # (e.g., changing to or from a structured dtype), and the 

3026 # order could have changed. So, change the mask type if 

3027 # needed and use astype instead of copy. 

3028 if self.dtype == obj.dtype: 

3029 _mask_dtype = _mask.dtype 

3030 else: 

3031 _mask_dtype = make_mask_descr(self.dtype) 

3032 

3033 if self.flags.c_contiguous: 

3034 order = "C" 

3035 elif self.flags.f_contiguous: 

3036 order = "F" 

3037 else: 

3038 order = "K" 

3039 

3040 _mask = _mask.astype(_mask_dtype, order) 

3041 else: 

3042 # Take a view so shape changes, etc., do not propagate back. 

3043 _mask = _mask.view() 

3044 else: 

3045 _mask = nomask 

3046 

3047 self._mask = _mask 

3048 # Finalize the mask 

3049 if self._mask is not nomask: 

3050 try: 

3051 self._mask.shape = self.shape 

3052 except ValueError: 

3053 self._mask = nomask 

3054 except (TypeError, AttributeError): 

3055 # When _mask.shape is not writable (because it's a void) 

3056 pass 

3057 

3058 # Finalize the fill_value 

3059 if self._fill_value is not None: 

3060 self._fill_value = _check_fill_value(self._fill_value, self.dtype) 

3061 elif self.dtype.names is not None: 

3062 # Finalize the default fill_value for structured arrays 

3063 self._fill_value = _check_fill_value(None, self.dtype) 

3064 

3065 def __array_wrap__(self, obj, context=None): 

3066 """ 

3067 Special hook for ufuncs. 

3068 

3069 Wraps the numpy array and sets the mask according to context. 

3070 

3071 """ 

3072 if obj is self: # for in-place operations 

3073 result = obj 

3074 else: 

3075 result = obj.view(type(self)) 

3076 result._update_from(self) 

3077 

3078 if context is not None: 

3079 result._mask = result._mask.copy() 

3080 func, args, out_i = context 

3081 # args sometimes contains outputs (gh-10459), which we don't want 

3082 input_args = args[:func.nin] 

3083 m = reduce(mask_or, [getmaskarray(arg) for arg in input_args]) 

3084 # Get the domain mask 

3085 domain = ufunc_domain.get(func, None) 

3086 if domain is not None: 

3087 # Take the domain, and make sure it's a ndarray 

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

3089 d = filled(domain(*input_args), True) 

3090 

3091 if d.any(): 

3092 # Fill the result where the domain is wrong 

3093 try: 

3094 # Binary domain: take the last value 

3095 fill_value = ufunc_fills[func][-1] 

3096 except TypeError: 

3097 # Unary domain: just use this one 

3098 fill_value = ufunc_fills[func] 

3099 except KeyError: 

3100 # Domain not recognized, use fill_value instead 

3101 fill_value = self.fill_value 

3102 

3103 np.copyto(result, fill_value, where=d) 

3104 

3105 # Update the mask 

3106 if m is nomask: 

3107 m = d 

3108 else: 

3109 # Don't modify inplace, we risk back-propagation 

3110 m = (m | d) 

3111 

3112 # Make sure the mask has the proper size 

3113 if result is not self and result.shape == () and m: 

3114 return masked 

3115 else: 

3116 result._mask = m 

3117 result._sharedmask = False 

3118 

3119 return result 

3120 

3121 def view(self, dtype=None, type=None, fill_value=None): 

3122 """ 

3123 Return a view of the MaskedArray data. 

3124 

3125 Parameters 

3126 ---------- 

3127 dtype : data-type or ndarray sub-class, optional 

3128 Data-type descriptor of the returned view, e.g., float32 or int16. 

3129 The default, None, results in the view having the same data-type 

3130 as `a`. As with ``ndarray.view``, dtype can also be specified as 

3131 an ndarray sub-class, which then specifies the type of the 

3132 returned object (this is equivalent to setting the ``type`` 

3133 parameter). 

3134 type : Python type, optional 

3135 Type of the returned view, either ndarray or a subclass. The 

3136 default None results in type preservation. 

3137 fill_value : scalar, optional 

3138 The value to use for invalid entries (None by default). 

3139 If None, then this argument is inferred from the passed `dtype`, or 

3140 in its absence the original array, as discussed in the notes below. 

3141 

3142 See Also 

3143 -------- 

3144 numpy.ndarray.view : Equivalent method on ndarray object. 

3145 

3146 Notes 

3147 ----- 

3148 

3149 ``a.view()`` is used two different ways: 

3150 

3151 ``a.view(some_dtype)`` or ``a.view(dtype=some_dtype)`` constructs a view 

3152 of the array's memory with a different data-type. This can cause a 

3153 reinterpretation of the bytes of memory. 

3154 

3155 ``a.view(ndarray_subclass)`` or ``a.view(type=ndarray_subclass)`` just 

3156 returns an instance of `ndarray_subclass` that looks at the same array 

3157 (same shape, dtype, etc.) This does not cause a reinterpretation of the 

3158 memory. 

3159 

3160 If `fill_value` is not specified, but `dtype` is specified (and is not 

3161 an ndarray sub-class), the `fill_value` of the MaskedArray will be 

3162 reset. If neither `fill_value` nor `dtype` are specified (or if 

3163 `dtype` is an ndarray sub-class), then the fill value is preserved. 

3164 Finally, if `fill_value` is specified, but `dtype` is not, the fill 

3165 value is set to the specified value. 

3166 

3167 For ``a.view(some_dtype)``, if ``some_dtype`` has a different number of 

3168 bytes per entry than the previous dtype (for example, converting a 

3169 regular array to a structured array), then the behavior of the view 

3170 cannot be predicted just from the superficial appearance of ``a`` (shown 

3171 by ``print(a)``). It also depends on exactly how ``a`` is stored in 

3172 memory. Therefore if ``a`` is C-ordered versus fortran-ordered, versus 

3173 defined as a slice or transpose, etc., the view may give different 

3174 results. 

3175 """ 

3176 

3177 if dtype is None: 

3178 if type is None: 

3179 output = ndarray.view(self) 

3180 else: 

3181 output = ndarray.view(self, type) 

3182 elif type is None: 

3183 try: 

3184 if issubclass(dtype, ndarray): 

3185 output = ndarray.view(self, dtype) 

3186 dtype = None 

3187 else: 

3188 output = ndarray.view(self, dtype) 

3189 except TypeError: 

3190 output = ndarray.view(self, dtype) 

3191 else: 

3192 output = ndarray.view(self, dtype, type) 

3193 

3194 # also make the mask be a view (so attr changes to the view's 

3195 # mask do no affect original object's mask) 

3196 # (especially important to avoid affecting np.masked singleton) 

3197 if getmask(output) is not nomask: 

3198 output._mask = output._mask.view() 

3199 

3200 # Make sure to reset the _fill_value if needed 

3201 if getattr(output, '_fill_value', None) is not None: 

3202 if fill_value is None: 

3203 if dtype is None: 

3204 pass # leave _fill_value as is 

3205 else: 

3206 output._fill_value = None 

3207 else: 

3208 output.fill_value = fill_value 

3209 return output 

3210 

3211 def __getitem__(self, indx): 

3212 """ 

3213 x.__getitem__(y) <==> x[y] 

3214 

3215 Return the item described by i, as a masked array. 

3216 

3217 """ 

3218 # We could directly use ndarray.__getitem__ on self. 

3219 # But then we would have to modify __array_finalize__ to prevent the 

3220 # mask of being reshaped if it hasn't been set up properly yet 

3221 # So it's easier to stick to the current version 

3222 dout = self.data[indx] 

3223 _mask = self._mask 

3224 

3225 def _is_scalar(m): 

3226 return not isinstance(m, np.ndarray) 

3227 

3228 def _scalar_heuristic(arr, elem): 

3229 """ 

3230 Return whether `elem` is a scalar result of indexing `arr`, or None 

3231 if undecidable without promoting nomask to a full mask 

3232 """ 

3233 # obviously a scalar 

3234 if not isinstance(elem, np.ndarray): 

3235 return True 

3236 

3237 # object array scalar indexing can return anything 

3238 elif arr.dtype.type is np.object_: 

3239 if arr.dtype is not elem.dtype: 

3240 # elem is an array, but dtypes do not match, so must be 

3241 # an element 

3242 return True 

3243 

3244 # well-behaved subclass that only returns 0d arrays when 

3245 # expected - this is not a scalar 

3246 elif type(arr).__getitem__ == ndarray.__getitem__: 

3247 return False 

3248 

3249 return None 

3250 

3251 if _mask is not nomask: 

3252 # _mask cannot be a subclass, so it tells us whether we should 

3253 # expect a scalar. It also cannot be of dtype object. 

3254 mout = _mask[indx] 

3255 scalar_expected = _is_scalar(mout) 

3256 

3257 else: 

3258 # attempt to apply the heuristic to avoid constructing a full mask 

3259 mout = nomask 

3260 scalar_expected = _scalar_heuristic(self.data, dout) 

3261 if scalar_expected is None: 

3262 # heuristics have failed 

3263 # construct a full array, so we can be certain. This is costly. 

3264 # we could also fall back on ndarray.__getitem__(self.data, indx) 

3265 scalar_expected = _is_scalar(getmaskarray(self)[indx]) 

3266 

3267 # Did we extract a single item? 

3268 if scalar_expected: 

3269 # A record 

3270 if isinstance(dout, np.void): 

3271 # We should always re-cast to mvoid, otherwise users can 

3272 # change masks on rows that already have masked values, but not 

3273 # on rows that have no masked values, which is inconsistent. 

3274 return mvoid(dout, mask=mout, hardmask=self._hardmask) 

3275 

3276 # special case introduced in gh-5962 

3277 elif (self.dtype.type is np.object_ and 

3278 isinstance(dout, np.ndarray) and 

3279 dout is not masked): 

3280 # If masked, turn into a MaskedArray, with everything masked. 

3281 if mout: 

3282 return MaskedArray(dout, mask=True) 

3283 else: 

3284 return dout 

3285 

3286 # Just a scalar 

3287 else: 

3288 if mout: 

3289 return masked 

3290 else: 

3291 return dout 

3292 else: 

3293 # Force dout to MA 

3294 dout = dout.view(type(self)) 

3295 # Inherit attributes from self 

3296 dout._update_from(self) 

3297 # Check the fill_value 

3298 if is_string_or_list_of_strings(indx): 

3299 if self._fill_value is not None: 

3300 dout._fill_value = self._fill_value[indx] 

3301 

3302 # Something like gh-15895 has happened if this check fails. 

3303 # _fill_value should always be an ndarray. 

3304 if not isinstance(dout._fill_value, np.ndarray): 

3305 raise RuntimeError('Internal NumPy error.') 

3306 # If we're indexing a multidimensional field in a 

3307 # structured array (such as dtype("(2,)i2,(2,)i1")), 

3308 # dimensionality goes up (M[field].ndim == M.ndim + 

3309 # M.dtype[field].ndim). That's fine for 

3310 # M[field] but problematic for M[field].fill_value 

3311 # which should have shape () to avoid breaking several 

3312 # methods. There is no great way out, so set to 

3313 # first element. See issue #6723. 

3314 if dout._fill_value.ndim > 0: 

3315 if not (dout._fill_value == 

3316 dout._fill_value.flat[0]).all(): 

3317 warnings.warn( 

3318 "Upon accessing multidimensional field " 

3319 f"{indx!s}, need to keep dimensionality " 

3320 "of fill_value at 0. Discarding " 

3321 "heterogeneous fill_value and setting " 

3322 f"all to {dout._fill_value[0]!s}.", 

3323 stacklevel=2) 

3324 # Need to use `.flat[0:1].squeeze(...)` instead of just 

3325 # `.flat[0]` to ensure the result is a 0d array and not 

3326 # a scalar. 

3327 dout._fill_value = dout._fill_value.flat[0:1].squeeze(axis=0) 

3328 dout._isfield = True 

3329 # Update the mask if needed 

3330 if mout is not nomask: 

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

3332 dout._mask = reshape(mout, dout.shape) 

3333 dout._sharedmask = True 

3334 # Note: Don't try to check for m.any(), that'll take too long 

3335 return dout 

3336 

3337 def __setitem__(self, indx, value): 

3338 """ 

3339 x.__setitem__(i, y) <==> x[i]=y 

3340 

3341 Set item described by index. If value is masked, masks those 

3342 locations. 

3343 

3344 """ 

3345 if self is masked: 

3346 raise MaskError('Cannot alter the masked element.') 

3347 _data = self._data 

3348 _mask = self._mask 

3349 if isinstance(indx, str): 

3350 _data[indx] = value 

3351 if _mask is nomask: 

3352 self._mask = _mask = make_mask_none(self.shape, self.dtype) 

3353 _mask[indx] = getmask(value) 

3354 return 

3355 

3356 _dtype = _data.dtype 

3357 

3358 if value is masked: 

3359 # The mask wasn't set: create a full version. 

3360 if _mask is nomask: 

3361 _mask = self._mask = make_mask_none(self.shape, _dtype) 

3362 # Now, set the mask to its value. 

3363 if _dtype.names is not None: 

3364 _mask[indx] = tuple([True] * len(_dtype.names)) 

3365 else: 

3366 _mask[indx] = True 

3367 return 

3368 

3369 # Get the _data part of the new value 

3370 dval = getattr(value, '_data', value) 

3371 # Get the _mask part of the new value 

3372 mval = getmask(value) 

3373 if _dtype.names is not None and mval is nomask: 

3374 mval = tuple([False] * len(_dtype.names)) 

3375 if _mask is nomask: 

3376 # Set the data, then the mask 

3377 _data[indx] = dval 

3378 if mval is not nomask: 

3379 _mask = self._mask = make_mask_none(self.shape, _dtype) 

3380 _mask[indx] = mval 

3381 elif not self._hardmask: 

3382 # Set the data, then the mask 

3383 if (isinstance(indx, masked_array) and 

3384 not isinstance(value, masked_array)): 

3385 _data[indx.data] = dval 

3386 else: 

3387 _data[indx] = dval 

3388 _mask[indx] = mval 

3389 elif hasattr(indx, 'dtype') and (indx.dtype == MaskType): 

3390 indx = indx * umath.logical_not(_mask) 

3391 _data[indx] = dval 

3392 else: 

3393 if _dtype.names is not None: 

3394 err_msg = "Flexible 'hard' masks are not yet supported." 

3395 raise NotImplementedError(err_msg) 

3396 mindx = mask_or(_mask[indx], mval, copy=True) 

3397 dindx = self._data[indx] 

3398 if dindx.size > 1: 

3399 np.copyto(dindx, dval, where=~mindx) 

3400 elif mindx is nomask: 

3401 dindx = dval 

3402 _data[indx] = dindx 

3403 _mask[indx] = mindx 

3404 return 

3405 

3406 # Define so that we can overwrite the setter. 

3407 @property 

3408 def dtype(self): 

3409 return super().dtype 

3410 

3411 @dtype.setter 

3412 def dtype(self, dtype): 

3413 super(MaskedArray, type(self)).dtype.__set__(self, dtype) 

3414 if self._mask is not nomask: 

3415 self._mask = self._mask.view(make_mask_descr(dtype), ndarray) 

3416 # Try to reset the shape of the mask (if we don't have a void). 

3417 # This raises a ValueError if the dtype change won't work. 

3418 try: 

3419 self._mask.shape = self.shape 

3420 except (AttributeError, TypeError): 

3421 pass 

3422 

3423 @property 

3424 def shape(self): 

3425 return super().shape 

3426 

3427 @shape.setter 

3428 def shape(self, shape): 

3429 super(MaskedArray, type(self)).shape.__set__(self, shape) 

3430 # Cannot use self._mask, since it may not (yet) exist when a 

3431 # masked matrix sets the shape. 

3432 if getmask(self) is not nomask: 

3433 self._mask.shape = self.shape 

3434 

3435 def __setmask__(self, mask, copy=False): 

3436 """ 

3437 Set the mask. 

3438 

3439 """ 

3440 idtype = self.dtype 

3441 current_mask = self._mask 

3442 if mask is masked: 

3443 mask = True 

3444 

3445 if current_mask is nomask: 

3446 # Make sure the mask is set 

3447 # Just don't do anything if there's nothing to do. 

3448 if mask is nomask: 

3449 return 

3450 current_mask = self._mask = make_mask_none(self.shape, idtype) 

3451 

3452 if idtype.names is None: 

3453 # No named fields. 

3454 # Hardmask: don't unmask the data 

3455 if self._hardmask: 

3456 current_mask |= mask 

3457 # Softmask: set everything to False 

3458 # If it's obviously a compatible scalar, use a quick update 

3459 # method. 

3460 elif isinstance(mask, (int, float, np.bool_, np.number)): 

3461 current_mask[...] = mask 

3462 # Otherwise fall back to the slower, general purpose way. 

3463 else: 

3464 current_mask.flat = mask 

3465 else: 

3466 # Named fields w/ 

3467 mdtype = current_mask.dtype 

3468 mask = np.array(mask, copy=False) 

3469 # Mask is a singleton 

3470 if not mask.ndim: 

3471 # It's a boolean : make a record 

3472 if mask.dtype.kind == 'b': 

3473 mask = np.array(tuple([mask.item()] * len(mdtype)), 

3474 dtype=mdtype) 

3475 # It's a record: make sure the dtype is correct 

3476 else: 

3477 mask = mask.astype(mdtype) 

3478 # Mask is a sequence 

3479 else: 

3480 # Make sure the new mask is a ndarray with the proper dtype 

3481 try: 

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

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

3484 except TypeError: 

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

3486 dtype=mdtype) 

3487 # Hardmask: don't unmask the data 

3488 if self._hardmask: 

3489 for n in idtype.names: 

3490 current_mask[n] |= mask[n] 

3491 # Softmask: set everything to False 

3492 # If it's obviously a compatible scalar, use a quick update 

3493 # method. 

3494 elif isinstance(mask, (int, float, np.bool_, np.number)): 

3495 current_mask[...] = mask 

3496 # Otherwise fall back to the slower, general purpose way. 

3497 else: 

3498 current_mask.flat = mask 

3499 # Reshape if needed 

3500 if current_mask.shape: 

3501 current_mask.shape = self.shape 

3502 return 

3503 

3504 _set_mask = __setmask__ 

3505 

3506 @property 

3507 def mask(self): 

3508 """ Current mask. """ 

3509 

3510 # We could try to force a reshape, but that wouldn't work in some 

3511 # cases. 

3512 # Return a view so that the dtype and shape cannot be changed in place 

3513 # This still preserves nomask by identity 

3514 return self._mask.view() 

3515 

3516 @mask.setter 

3517 def mask(self, value): 

3518 self.__setmask__(value) 

3519 

3520 @property 

3521 def recordmask(self): 

3522 """ 

3523 Get or set the mask of the array if it has no named fields. For 

3524 structured arrays, returns a ndarray of booleans where entries are 

3525 ``True`` if **all** the fields are masked, ``False`` otherwise: 

3526 

3527 >>> x = np.ma.array([(1, 1), (2, 2), (3, 3), (4, 4), (5, 5)], 

3528 ... mask=[(0, 0), (1, 0), (1, 1), (0, 1), (0, 0)], 

3529 ... dtype=[('a', int), ('b', int)]) 

3530 >>> x.recordmask 

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

3532 """ 

3533 

3534 _mask = self._mask.view(ndarray) 

3535 if _mask.dtype.names is None: 

3536 return _mask 

3537 return np.all(flatten_structured_array(_mask), axis=-1) 

3538 

3539 @recordmask.setter 

3540 def recordmask(self, mask): 

3541 raise NotImplementedError("Coming soon: setting the mask per records!") 

3542 

3543 def harden_mask(self): 

3544 """ 

3545 Force the mask to hard, preventing unmasking by assignment. 

3546 

3547 Whether the mask of a masked array is hard or soft is determined by 

3548 its `~ma.MaskedArray.hardmask` property. `harden_mask` sets 

3549 `~ma.MaskedArray.hardmask` to ``True`` (and returns the modified 

3550 self). 

3551 

3552 See Also 

3553 -------- 

3554 ma.MaskedArray.hardmask 

3555 ma.MaskedArray.soften_mask 

3556 

3557 """ 

3558 self._hardmask = True 

3559 return self 

3560 

3561 def soften_mask(self): 

3562 """ 

3563 Force the mask to soft (default), allowing unmasking by assignment. 

3564 

3565 Whether the mask of a masked array is hard or soft is determined by 

3566 its `~ma.MaskedArray.hardmask` property. `soften_mask` sets 

3567 `~ma.MaskedArray.hardmask` to ``False`` (and returns the modified 

3568 self). 

3569 

3570 See Also 

3571 -------- 

3572 ma.MaskedArray.hardmask 

3573 ma.MaskedArray.harden_mask 

3574 

3575 """ 

3576 self._hardmask = False 

3577 return self 

3578 

3579 @property 

3580 def hardmask(self): 

3581 """ 

3582 Specifies whether values can be unmasked through assignments. 

3583 

3584 By default, assigning definite values to masked array entries will 

3585 unmask them. When `hardmask` is ``True``, the mask will not change 

3586 through assignments. 

3587 

3588 See Also 

3589 -------- 

3590 ma.MaskedArray.harden_mask 

3591 ma.MaskedArray.soften_mask 

3592 

3593 Examples 

3594 -------- 

3595 >>> x = np.arange(10) 

3596 >>> m = np.ma.masked_array(x, x>5) 

3597 >>> assert not m.hardmask 

3598 

3599 Since `m` has a soft mask, assigning an element value unmasks that 

3600 element: 

3601 

3602 >>> m[8] = 42 

3603 >>> m 

3604 masked_array(data=[0, 1, 2, 3, 4, 5, --, --, 42, --], 

3605 mask=[False, False, False, False, False, False, 

3606 True, True, False, True], 

3607 fill_value=999999) 

3608 

3609 After hardening, the mask is not affected by assignments: 

3610 

3611 >>> hardened = np.ma.harden_mask(m) 

3612 >>> assert m.hardmask and hardened is m 

3613 >>> m[:] = 23 

3614 >>> m 

3615 masked_array(data=[23, 23, 23, 23, 23, 23, --, --, 23, --], 

3616 mask=[False, False, False, False, False, False, 

3617 True, True, False, True], 

3618 fill_value=999999) 

3619 

3620 """ 

3621 return self._hardmask 

3622 

3623 def unshare_mask(self): 

3624 """ 

3625 Copy the mask and set the `sharedmask` flag to ``False``. 

3626 

3627 Whether the mask is shared between masked arrays can be seen from 

3628 the `sharedmask` property. `unshare_mask` ensures the mask is not 

3629 shared. A copy of the mask is only made if it was shared. 

3630 

3631 See Also 

3632 -------- 

3633 sharedmask 

3634 

3635 """ 

3636 if self._sharedmask: 

3637 self._mask = self._mask.copy() 

3638 self._sharedmask = False 

3639 return self 

3640 

3641 @property 

3642 def sharedmask(self): 

3643 """ Share status of the mask (read-only). """ 

3644 return self._sharedmask 

3645 

3646 def shrink_mask(self): 

3647 """ 

3648 Reduce a mask to nomask when possible. 

3649 

3650 Parameters 

3651 ---------- 

3652 None 

3653 

3654 Returns 

3655 ------- 

3656 None 

3657 

3658 Examples 

3659 -------- 

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

3661 >>> x.mask 

3662 array([[False, False], 

3663 [False, False]]) 

3664 >>> x.shrink_mask() 

3665 masked_array( 

3666 data=[[1, 2], 

3667 [3, 4]], 

3668 mask=False, 

3669 fill_value=999999) 

3670 >>> x.mask 

3671 False 

3672 

3673 """ 

3674 self._mask = _shrink_mask(self._mask) 

3675 return self 

3676 

3677 @property 

3678 def baseclass(self): 

3679 """ Class of the underlying data (read-only). """ 

3680 return self._baseclass 

3681 

3682 def _get_data(self): 

3683 """ 

3684 Returns the underlying data, as a view of the masked array. 

3685 

3686 If the underlying data is a subclass of :class:`numpy.ndarray`, it is 

3687 returned as such. 

3688 

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

3690 >>> x.data 

3691 matrix([[1, 2], 

3692 [3, 4]]) 

3693 

3694 The type of the data can be accessed through the :attr:`baseclass` 

3695 attribute. 

3696 """ 

3697 return ndarray.view(self, self._baseclass) 

3698 

3699 _data = property(fget=_get_data) 

3700 data = property(fget=_get_data) 

3701 

3702 @property 

3703 def flat(self): 

3704 """ Return a flat iterator, or set a flattened version of self to value. """ 

3705 return MaskedIterator(self) 

3706 

3707 @flat.setter 

3708 def flat(self, value): 

3709 y = self.ravel() 

3710 y[:] = value 

3711 

3712 @property 

3713 def fill_value(self): 

3714 """ 

3715 The filling value of the masked array is a scalar. When setting, None 

3716 will set to a default based on the data type. 

3717 

3718 Examples 

3719 -------- 

3720 >>> for dt in [np.int32, np.int64, np.float64, np.complex128]: 

3721 ... np.ma.array([0, 1], dtype=dt).get_fill_value() 

3722 ... 

3723 999999 

3724 999999 

3725 1e+20 

3726 (1e+20+0j) 

3727 

3728 >>> x = np.ma.array([0, 1.], fill_value=-np.inf) 

3729 >>> x.fill_value 

3730 -inf 

3731 >>> x.fill_value = np.pi 

3732 >>> x.fill_value 

3733 3.1415926535897931 # may vary 

3734 

3735 Reset to default: 

3736 

3737 >>> x.fill_value = None 

3738 >>> x.fill_value 

3739 1e+20 

3740 

3741 """ 

3742 if self._fill_value is None: 

3743 self._fill_value = _check_fill_value(None, self.dtype) 

3744 

3745 # Temporary workaround to account for the fact that str and bytes 

3746 # scalars cannot be indexed with (), whereas all other numpy 

3747 # scalars can. See issues #7259 and #7267. 

3748 # The if-block can be removed after #7267 has been fixed. 

3749 if isinstance(self._fill_value, ndarray): 

3750 return self._fill_value[()] 

3751 return self._fill_value 

3752 

3753 @fill_value.setter 

3754 def fill_value(self, value=None): 

3755 target = _check_fill_value(value, self.dtype) 

3756 if not target.ndim == 0: 

3757 # 2019-11-12, 1.18.0 

3758 warnings.warn( 

3759 "Non-scalar arrays for the fill value are deprecated. Use " 

3760 "arrays with scalar values instead. The filled function " 

3761 "still supports any array as `fill_value`.", 

3762 DeprecationWarning, stacklevel=2) 

3763 

3764 _fill_value = self._fill_value 

3765 if _fill_value is None: 

3766 # Create the attribute if it was undefined 

3767 self._fill_value = target 

3768 else: 

3769 # Don't overwrite the attribute, just fill it (for propagation) 

3770 _fill_value[()] = target 

3771 

3772 # kept for compatibility 

3773 get_fill_value = fill_value.fget 

3774 set_fill_value = fill_value.fset 

3775 

3776 def filled(self, fill_value=None): 

3777 """ 

3778 Return a copy of self, with masked values filled with a given value. 

3779 **However**, if there are no masked values to fill, self will be 

3780 returned instead as an ndarray. 

3781 

3782 Parameters 

3783 ---------- 

3784 fill_value : array_like, optional 

3785 The value to use for invalid entries. Can be scalar or non-scalar. 

3786 If non-scalar, the resulting ndarray must be broadcastable over 

3787 input array. Default is None, in which case, the `fill_value` 

3788 attribute of the array is used instead. 

3789 

3790 Returns 

3791 ------- 

3792 filled_array : ndarray 

3793 A copy of ``self`` with invalid entries replaced by *fill_value* 

3794 (be it the function argument or the attribute of ``self``), or 

3795 ``self`` itself as an ndarray if there are no invalid entries to 

3796 be replaced. 

3797 

3798 Notes 

3799 ----- 

3800 The result is **not** a MaskedArray! 

3801 

3802 Examples 

3803 -------- 

3804 >>> x = np.ma.array([1,2,3,4,5], mask=[0,0,1,0,1], fill_value=-999) 

3805 >>> x.filled() 

3806 array([ 1, 2, -999, 4, -999]) 

3807 >>> x.filled(fill_value=1000) 

3808 array([ 1, 2, 1000, 4, 1000]) 

3809 >>> type(x.filled()) 

3810 <class 'numpy.ndarray'> 

3811 

3812 Subclassing is preserved. This means that if, e.g., the data part of 

3813 the masked array is a recarray, `filled` returns a recarray: 

3814 

3815 >>> x = np.array([(-1, 2), (-3, 4)], dtype='i8,i8').view(np.recarray) 

3816 >>> m = np.ma.array(x, mask=[(True, False), (False, True)]) 

3817 >>> m.filled() 

3818 rec.array([(999999, 2), ( -3, 999999)], 

3819 dtype=[('f0', '<i8'), ('f1', '<i8')]) 

3820 """ 

3821 m = self._mask 

3822 if m is nomask: 

3823 return self._data 

3824 

3825 if fill_value is None: 

3826 fill_value = self.fill_value 

3827 else: 

3828 fill_value = _check_fill_value(fill_value, self.dtype) 

3829 

3830 if self is masked_singleton: 

3831 return np.asanyarray(fill_value) 

3832 

3833 if m.dtype.names is not None: 

3834 result = self._data.copy('K') 

3835 _recursive_filled(result, self._mask, fill_value) 

3836 elif not m.any(): 

3837 return self._data 

3838 else: 

3839 result = self._data.copy('K') 

3840 try: 

3841 np.copyto(result, fill_value, where=m) 

3842 except (TypeError, AttributeError): 

3843 fill_value = narray(fill_value, dtype=object) 

3844 d = result.astype(object) 

3845 result = np.choose(m, (d, fill_value)) 

3846 except IndexError: 

3847 # ok, if scalar 

3848 if self._data.shape: 

3849 raise 

3850 elif m: 

3851 result = np.array(fill_value, dtype=self.dtype) 

3852 else: 

3853 result = self._data 

3854 return result 

3855 

3856 def compressed(self): 

3857 """ 

3858 Return all the non-masked data as a 1-D array. 

3859 

3860 Returns 

3861 ------- 

3862 data : ndarray 

3863 A new `ndarray` holding the non-masked data is returned. 

3864 

3865 Notes 

3866 ----- 

3867 The result is **not** a MaskedArray! 

3868 

3869 Examples 

3870 -------- 

3871 >>> x = np.ma.array(np.arange(5), mask=[0]*2 + [1]*3) 

3872 >>> x.compressed() 

3873 array([0, 1]) 

3874 >>> type(x.compressed()) 

3875 <class 'numpy.ndarray'> 

3876 

3877 """ 

3878 data = ndarray.ravel(self._data) 

3879 if self._mask is not nomask: 

3880 data = data.compress(np.logical_not(ndarray.ravel(self._mask))) 

3881 return data 

3882 

3883 def compress(self, condition, axis=None, out=None): 

3884 """ 

3885 Return `a` where condition is ``True``. 

3886 

3887 If condition is a `~ma.MaskedArray`, missing values are considered 

3888 as ``False``. 

3889 

3890 Parameters 

3891 ---------- 

3892 condition : var 

3893 Boolean 1-d array selecting which entries to return. If len(condition) 

3894 is less than the size of a along the axis, then output is truncated 

3895 to length of condition array. 

3896 axis : {None, int}, optional 

3897 Axis along which the operation must be performed. 

3898 out : {None, ndarray}, optional 

3899 Alternative output array in which to place the result. It must have 

3900 the same shape as the expected output but the type will be cast if 

3901 necessary. 

3902 

3903 Returns 

3904 ------- 

3905 result : MaskedArray 

3906 A :class:`~ma.MaskedArray` object. 

3907 

3908 Notes 

3909 ----- 

3910 Please note the difference with :meth:`compressed` ! 

3911 The output of :meth:`compress` has a mask, the output of 

3912 :meth:`compressed` does not. 

3913 

3914 Examples 

3915 -------- 

3916 >>> x = np.ma.array([[1,2,3],[4,5,6],[7,8,9]], mask=[0] + [1,0]*4) 

3917 >>> x 

3918 masked_array( 

3919 data=[[1, --, 3], 

3920 [--, 5, --], 

3921 [7, --, 9]], 

3922 mask=[[False, True, False], 

3923 [ True, False, True], 

3924 [False, True, False]], 

3925 fill_value=999999) 

3926 >>> x.compress([1, 0, 1]) 

3927 masked_array(data=[1, 3], 

3928 mask=[False, False], 

3929 fill_value=999999) 

3930 

3931 >>> x.compress([1, 0, 1], axis=1) 

3932 masked_array( 

3933 data=[[1, 3], 

3934 [--, --], 

3935 [7, 9]], 

3936 mask=[[False, False], 

3937 [ True, True], 

3938 [False, False]], 

3939 fill_value=999999) 

3940 

3941 """ 

3942 # Get the basic components 

3943 (_data, _mask) = (self._data, self._mask) 

3944 

3945 # Force the condition to a regular ndarray and forget the missing 

3946 # values. 

3947 condition = np.asarray(condition) 

3948 

3949 _new = _data.compress(condition, axis=axis, out=out).view(type(self)) 

3950 _new._update_from(self) 

3951 if _mask is not nomask: 

3952 _new._mask = _mask.compress(condition, axis=axis) 

3953 return _new 

3954 

3955 def _insert_masked_print(self): 

3956 """ 

3957 Replace masked values with masked_print_option, casting all innermost 

3958 dtypes to object. 

3959 """ 

3960 if masked_print_option.enabled(): 

3961 mask = self._mask 

3962 if mask is nomask: 

3963 res = self._data 

3964 else: 

3965 # convert to object array to make filled work 

3966 data = self._data 

3967 # For big arrays, to avoid a costly conversion to the 

3968 # object dtype, extract the corners before the conversion. 

3969 print_width = (self._print_width if self.ndim > 1 

3970 else self._print_width_1d) 

3971 for axis in range(self.ndim): 

3972 if data.shape[axis] > print_width: 

3973 ind = print_width // 2 

3974 arr = np.split(data, (ind, -ind), axis=axis) 

3975 data = np.concatenate((arr[0], arr[2]), axis=axis) 

3976 arr = np.split(mask, (ind, -ind), axis=axis) 

3977 mask = np.concatenate((arr[0], arr[2]), axis=axis) 

3978 

3979 rdtype = _replace_dtype_fields(self.dtype, "O") 

3980 res = data.astype(rdtype) 

3981 _recursive_printoption(res, mask, masked_print_option) 

3982 else: 

3983 res = self.filled(self.fill_value) 

3984 return res 

3985 

3986 def __str__(self): 

3987 return str(self._insert_masked_print()) 

3988 

3989 def __repr__(self): 

3990 """ 

3991 Literal string representation. 

3992 

3993 """ 

3994 if self._baseclass is np.ndarray: 

3995 name = 'array' 

3996 else: 

3997 name = self._baseclass.__name__ 

3998 

3999 

4000 # 2016-11-19: Demoted to legacy format 

4001 if np.core.arrayprint._get_legacy_print_mode() <= 113: 

4002 is_long = self.ndim > 1 

4003 parameters = dict( 

4004 name=name, 

4005 nlen=" " * len(name), 

4006 data=str(self), 

4007 mask=str(self._mask), 

4008 fill=str(self.fill_value), 

4009 dtype=str(self.dtype) 

4010 ) 

4011 is_structured = bool(self.dtype.names) 

4012 key = '{}_{}'.format( 

4013 'long' if is_long else 'short', 

4014 'flx' if is_structured else 'std' 

4015 ) 

4016 return _legacy_print_templates[key] % parameters 

4017 

4018 prefix = f"masked_{name}(" 

4019 

4020 dtype_needed = ( 

4021 not np.core.arrayprint.dtype_is_implied(self.dtype) or 

4022 np.all(self.mask) or 

4023 self.size == 0 

4024 ) 

4025 

4026 # determine which keyword args need to be shown 

4027 keys = ['data', 'mask', 'fill_value'] 

4028 if dtype_needed: 

4029 keys.append('dtype') 

4030 

4031 # array has only one row (non-column) 

4032 is_one_row = builtins.all(dim == 1 for dim in self.shape[:-1]) 

4033 

4034 # choose what to indent each keyword with 

4035 min_indent = 2 

4036 if is_one_row: 

4037 # first key on the same line as the type, remaining keys 

4038 # aligned by equals 

4039 indents = {} 

4040 indents[keys[0]] = prefix 

4041 for k in keys[1:]: 

4042 n = builtins.max(min_indent, len(prefix + keys[0]) - len(k)) 

4043 indents[k] = ' ' * n 

4044 prefix = '' # absorbed into the first indent 

4045 else: 

4046 # each key on its own line, indented by two spaces 

4047 indents = {k: ' ' * min_indent for k in keys} 

4048 prefix = prefix + '\n' # first key on the next line 

4049 

4050 # format the field values 

4051 reprs = {} 

4052 reprs['data'] = np.array2string( 

4053 self._insert_masked_print(), 

4054 separator=", ", 

4055 prefix=indents['data'] + 'data=', 

4056 suffix=',') 

4057 reprs['mask'] = np.array2string( 

4058 self._mask, 

4059 separator=", ", 

4060 prefix=indents['mask'] + 'mask=', 

4061 suffix=',') 

4062 reprs['fill_value'] = repr(self.fill_value) 

4063 if dtype_needed: 

4064 reprs['dtype'] = np.core.arrayprint.dtype_short_repr(self.dtype) 

4065 

4066 # join keys with values and indentations 

4067 result = ',\n'.join( 

4068 '{}{}={}'.format(indents[k], k, reprs[k]) 

4069 for k in keys 

4070 ) 

4071 return prefix + result + ')' 

4072 

4073 def _delegate_binop(self, other): 

4074 # This emulates the logic in 

4075 # private/binop_override.h:forward_binop_should_defer 

4076 if isinstance(other, type(self)): 

4077 return False 

4078 array_ufunc = getattr(other, "__array_ufunc__", False) 

4079 if array_ufunc is False: 

4080 other_priority = getattr(other, "__array_priority__", -1000000) 

4081 return self.__array_priority__ < other_priority 

4082 else: 

4083 # If array_ufunc is not None, it will be called inside the ufunc; 

4084 # None explicitly tells us to not call the ufunc, i.e., defer. 

4085 return array_ufunc is None 

4086 

4087 def _comparison(self, other, compare): 

4088 """Compare self with other using operator.eq or operator.ne. 

4089 

4090 When either of the elements is masked, the result is masked as well, 

4091 but the underlying boolean data are still set, with self and other 

4092 considered equal if both are masked, and unequal otherwise. 

4093 

4094 For structured arrays, all fields are combined, with masked values 

4095 ignored. The result is masked if all fields were masked, with self 

4096 and other considered equal only if both were fully masked. 

4097 """ 

4098 omask = getmask(other) 

4099 smask = self.mask 

4100 mask = mask_or(smask, omask, copy=True) 

4101 

4102 odata = getdata(other) 

4103 if mask.dtype.names is not None: 

4104 # only == and != are reasonably defined for structured dtypes, 

4105 # so give up early for all other comparisons: 

4106 if compare not in (operator.eq, operator.ne): 

4107 return NotImplemented 

4108 # For possibly masked structured arrays we need to be careful, 

4109 # since the standard structured array comparison will use all 

4110 # fields, masked or not. To avoid masked fields influencing the 

4111 # outcome, we set all masked fields in self to other, so they'll 

4112 # count as equal. To prepare, we ensure we have the right shape. 

4113 broadcast_shape = np.broadcast(self, odata).shape 

4114 sbroadcast = np.broadcast_to(self, broadcast_shape, subok=True) 

4115 sbroadcast._mask = mask 

4116 sdata = sbroadcast.filled(odata) 

4117 # Now take care of the mask; the merged mask should have an item 

4118 # masked if all fields were masked (in one and/or other). 

4119 mask = (mask == np.ones((), mask.dtype)) 

4120 

4121 else: 

4122 # For regular arrays, just use the data as they come. 

4123 sdata = self.data 

4124 

4125 check = compare(sdata, odata) 

4126 

4127 if isinstance(check, (np.bool_, bool)): 

4128 return masked if mask else check 

4129 

4130 if mask is not nomask and compare in (operator.eq, operator.ne): 

4131 # Adjust elements that were masked, which should be treated 

4132 # as equal if masked in both, unequal if masked in one. 

4133 # Note that this works automatically for structured arrays too. 

4134 # Ignore this for operations other than `==` and `!=` 

4135 check = np.where(mask, compare(smask, omask), check) 

4136 if mask.shape != check.shape: 

4137 # Guarantee consistency of the shape, making a copy since the 

4138 # the mask may need to get written to later. 

4139 mask = np.broadcast_to(mask, check.shape).copy() 

4140 

4141 check = check.view(type(self)) 

4142 check._update_from(self) 

4143 check._mask = mask 

4144 

4145 # Cast fill value to bool_ if needed. If it cannot be cast, the 

4146 # default boolean fill value is used. 

4147 if check._fill_value is not None: 

4148 try: 

4149 fill = _check_fill_value(check._fill_value, np.bool_) 

4150 except (TypeError, ValueError): 

4151 fill = _check_fill_value(None, np.bool_) 

4152 check._fill_value = fill 

4153 

4154 return check 

4155 

4156 def __eq__(self, other): 

4157 """Check whether other equals self elementwise. 

4158 

4159 When either of the elements is masked, the result is masked as well, 

4160 but the underlying boolean data are still set, with self and other 

4161 considered equal if both are masked, and unequal otherwise. 

4162 

4163 For structured arrays, all fields are combined, with masked values 

4164 ignored. The result is masked if all fields were masked, with self 

4165 and other considered equal only if both were fully masked. 

4166 """ 

4167 return self._comparison(other, operator.eq) 

4168 

4169 def __ne__(self, other): 

4170 """Check whether other does not equal self elementwise. 

4171 

4172 When either of the elements is masked, the result is masked as well, 

4173 but the underlying boolean data are still set, with self and other 

4174 considered equal if both are masked, and unequal otherwise. 

4175 

4176 For structured arrays, all fields are combined, with masked values 

4177 ignored. The result is masked if all fields were masked, with self 

4178 and other considered equal only if both were fully masked. 

4179 """ 

4180 return self._comparison(other, operator.ne) 

4181 

4182 # All other comparisons: 

4183 def __le__(self, other): 

4184 return self._comparison(other, operator.le) 

4185 

4186 def __lt__(self, other): 

4187 return self._comparison(other, operator.lt) 

4188 

4189 def __ge__(self, other): 

4190 return self._comparison(other, operator.ge) 

4191 

4192 def __gt__(self, other): 

4193 return self._comparison(other, operator.gt) 

4194 

4195 def __add__(self, other): 

4196 """ 

4197 Add self to other, and return a new masked array. 

4198 

4199 """ 

4200 if self._delegate_binop(other): 

4201 return NotImplemented 

4202 return add(self, other) 

4203 

4204 def __radd__(self, other): 

4205 """ 

4206 Add other to self, and return a new masked array. 

4207 

4208 """ 

4209 # In analogy with __rsub__ and __rdiv__, use original order: 

4210 # we get here from `other + self`. 

4211 return add(other, self) 

4212 

4213 def __sub__(self, other): 

4214 """ 

4215 Subtract other from self, and return a new masked array. 

4216 

4217 """ 

4218 if self._delegate_binop(other): 

4219 return NotImplemented 

4220 return subtract(self, other) 

4221 

4222 def __rsub__(self, other): 

4223 """ 

4224 Subtract self from other, and return a new masked array. 

4225 

4226 """ 

4227 return subtract(other, self) 

4228 

4229 def __mul__(self, other): 

4230 "Multiply self by other, and return a new masked array." 

4231 if self._delegate_binop(other): 

4232 return NotImplemented 

4233 return multiply(self, other) 

4234 

4235 def __rmul__(self, other): 

4236 """ 

4237 Multiply other by self, and return a new masked array. 

4238 

4239 """ 

4240 # In analogy with __rsub__ and __rdiv__, use original order: 

4241 # we get here from `other * self`. 

4242 return multiply(other, self) 

4243 

4244 def __div__(self, other): 

4245 """ 

4246 Divide other into self, and return a new masked array. 

4247 

4248 """ 

4249 if self._delegate_binop(other): 

4250 return NotImplemented 

4251 return divide(self, other) 

4252 

4253 def __truediv__(self, other): 

4254 """ 

4255 Divide other into self, and return a new masked array. 

4256 

4257 """ 

4258 if self._delegate_binop(other): 

4259 return NotImplemented 

4260 return true_divide(self, other) 

4261 

4262 def __rtruediv__(self, other): 

4263 """ 

4264 Divide self into other, and return a new masked array. 

4265 

4266 """ 

4267 return true_divide(other, self) 

4268 

4269 def __floordiv__(self, other): 

4270 """ 

4271 Divide other into self, and return a new masked array. 

4272 

4273 """ 

4274 if self._delegate_binop(other): 

4275 return NotImplemented 

4276 return floor_divide(self, other) 

4277 

4278 def __rfloordiv__(self, other): 

4279 """ 

4280 Divide self into other, and return a new masked array. 

4281 

4282 """ 

4283 return floor_divide(other, self) 

4284 

4285 def __pow__(self, other): 

4286 """ 

4287 Raise self to the power other, masking the potential NaNs/Infs 

4288 

4289 """ 

4290 if self._delegate_binop(other): 

4291 return NotImplemented 

4292 return power(self, other) 

4293 

4294 def __rpow__(self, other): 

4295 """ 

4296 Raise other to the power self, masking the potential NaNs/Infs 

4297 

4298 """ 

4299 return power(other, self) 

4300 

4301 def __iadd__(self, other): 

4302 """ 

4303 Add other to self in-place. 

4304 

4305 """ 

4306 m = getmask(other) 

4307 if self._mask is nomask: 

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

4309 self._mask = make_mask_none(self.shape, self.dtype) 

4310 self._mask += m 

4311 else: 

4312 if m is not nomask: 

4313 self._mask += m 

4314 other_data = getdata(other) 

4315 other_data = np.where(self._mask, other_data.dtype.type(0), other_data) 

4316 self._data.__iadd__(other_data) 

4317 return self 

4318 

4319 def __isub__(self, other): 

4320 """ 

4321 Subtract other from self in-place. 

4322 

4323 """ 

4324 m = getmask(other) 

4325 if self._mask is nomask: 

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

4327 self._mask = make_mask_none(self.shape, self.dtype) 

4328 self._mask += m 

4329 elif m is not nomask: 

4330 self._mask += m 

4331 other_data = getdata(other) 

4332 other_data = np.where(self._mask, other_data.dtype.type(0), other_data) 

4333 self._data.__isub__(other_data) 

4334 return self 

4335 

4336 def __imul__(self, other): 

4337 """ 

4338 Multiply self by other in-place. 

4339 

4340 """ 

4341 m = getmask(other) 

4342 if self._mask is nomask: 

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

4344 self._mask = make_mask_none(self.shape, self.dtype) 

4345 self._mask += m 

4346 elif m is not nomask: 

4347 self._mask += m 

4348 other_data = getdata(other) 

4349 other_data = np.where(self._mask, other_data.dtype.type(1), other_data) 

4350 self._data.__imul__(other_data) 

4351 return self 

4352 

4353 def __idiv__(self, other): 

4354 """ 

4355 Divide self by other in-place. 

4356 

4357 """ 

4358 other_data = getdata(other) 

4359 dom_mask = _DomainSafeDivide().__call__(self._data, other_data) 

4360 other_mask = getmask(other) 

4361 new_mask = mask_or(other_mask, dom_mask) 

4362 # The following 4 lines control the domain filling 

4363 if dom_mask.any(): 

4364 (_, fval) = ufunc_fills[np.divide] 

4365 other_data = np.where( 

4366 dom_mask, other_data.dtype.type(fval), other_data) 

4367 self._mask |= new_mask 

4368 other_data = np.where(self._mask, other_data.dtype.type(1), other_data) 

4369 self._data.__idiv__(other_data) 

4370 return self 

4371 

4372 def __ifloordiv__(self, other): 

4373 """ 

4374 Floor divide self by other in-place. 

4375 

4376 """ 

4377 other_data = getdata(other) 

4378 dom_mask = _DomainSafeDivide().__call__(self._data, other_data) 

4379 other_mask = getmask(other) 

4380 new_mask = mask_or(other_mask, dom_mask) 

4381 # The following 3 lines control the domain filling 

4382 if dom_mask.any(): 

4383 (_, fval) = ufunc_fills[np.floor_divide] 

4384 other_data = np.where( 

4385 dom_mask, other_data.dtype.type(fval), other_data) 

4386 self._mask |= new_mask 

4387 other_data = np.where(self._mask, other_data.dtype.type(1), other_data) 

4388 self._data.__ifloordiv__(other_data) 

4389 return self 

4390 

4391 def __itruediv__(self, other): 

4392 """ 

4393 True divide self by other in-place. 

4394 

4395 """ 

4396 other_data = getdata(other) 

4397 dom_mask = _DomainSafeDivide().__call__(self._data, other_data) 

4398 other_mask = getmask(other) 

4399 new_mask = mask_or(other_mask, dom_mask) 

4400 # The following 3 lines control the domain filling 

4401 if dom_mask.any(): 

4402 (_, fval) = ufunc_fills[np.true_divide] 

4403 other_data = np.where( 

4404 dom_mask, other_data.dtype.type(fval), other_data) 

4405 self._mask |= new_mask 

4406 other_data = np.where(self._mask, other_data.dtype.type(1), other_data) 

4407 self._data.__itruediv__(other_data) 

4408 return self 

4409 

4410 def __ipow__(self, other): 

4411 """ 

4412 Raise self to the power other, in place. 

4413 

4414 """ 

4415 other_data = getdata(other) 

4416 other_data = np.where(self._mask, other_data.dtype.type(1), other_data) 

4417 other_mask = getmask(other) 

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

4419 self._data.__ipow__(other_data) 

4420 invalid = np.logical_not(np.isfinite(self._data)) 

4421 if invalid.any(): 

4422 if self._mask is not nomask: 

4423 self._mask |= invalid 

4424 else: 

4425 self._mask = invalid 

4426 np.copyto(self._data, self.fill_value, where=invalid) 

4427 new_mask = mask_or(other_mask, invalid) 

4428 self._mask = mask_or(self._mask, new_mask) 

4429 return self 

4430 

4431 def __float__(self): 

4432 """ 

4433 Convert to float. 

4434 

4435 """ 

4436 if self.size > 1: 

4437 raise TypeError("Only length-1 arrays can be converted " 

4438 "to Python scalars") 

4439 elif self._mask: 

4440 warnings.warn("Warning: converting a masked element to nan.", stacklevel=2) 

4441 return np.nan 

4442 return float(self.item()) 

4443 

4444 def __int__(self): 

4445 """ 

4446 Convert to int. 

4447 

4448 """ 

4449 if self.size > 1: 

4450 raise TypeError("Only length-1 arrays can be converted " 

4451 "to Python scalars") 

4452 elif self._mask: 

4453 raise MaskError('Cannot convert masked element to a Python int.') 

4454 return int(self.item()) 

4455 

4456 @property 

4457 def imag(self): 

4458 """ 

4459 The imaginary part of the masked array. 

4460 

4461 This property is a view on the imaginary part of this `MaskedArray`. 

4462 

4463 See Also 

4464 -------- 

4465 real 

4466 

4467 Examples 

4468 -------- 

4469 >>> x = np.ma.array([1+1.j, -2j, 3.45+1.6j], mask=[False, True, False]) 

4470 >>> x.imag 

4471 masked_array(data=[1.0, --, 1.6], 

4472 mask=[False, True, False], 

4473 fill_value=1e+20) 

4474 

4475 """ 

4476 result = self._data.imag.view(type(self)) 

4477 result.__setmask__(self._mask) 

4478 return result 

4479 

4480 # kept for compatibility 

4481 get_imag = imag.fget 

4482 

4483 @property 

4484 def real(self): 

4485 """ 

4486 The real part of the masked array. 

4487 

4488 This property is a view on the real part of this `MaskedArray`. 

4489 

4490 See Also 

4491 -------- 

4492 imag 

4493 

4494 Examples 

4495 -------- 

4496 >>> x = np.ma.array([1+1.j, -2j, 3.45+1.6j], mask=[False, True, False]) 

4497 >>> x.real 

4498 masked_array(data=[1.0, --, 3.45], 

4499 mask=[False, True, False], 

4500 fill_value=1e+20) 

4501 

4502 """ 

4503 result = self._data.real.view(type(self)) 

4504 result.__setmask__(self._mask) 

4505 return result 

4506 

4507 # kept for compatibility 

4508 get_real = real.fget 

4509 

4510 def count(self, axis=None, keepdims=np._NoValue): 

4511 """ 

4512 Count the non-masked elements of the array along the given axis. 

4513 

4514 Parameters 

4515 ---------- 

4516 axis : None or int or tuple of ints, optional 

4517 Axis or axes along which the count is performed. 

4518 The default, None, performs the count over all 

4519 the dimensions of the input array. `axis` may be negative, in 

4520 which case it counts from the last to the first axis. 

4521 

4522 .. versionadded:: 1.10.0 

4523 

4524 If this is a tuple of ints, the count is performed on multiple 

4525 axes, instead of a single axis or all the axes as before. 

4526 keepdims : bool, optional 

4527 If this is set to True, the axes which are reduced are left 

4528 in the result as dimensions with size one. With this option, 

4529 the result will broadcast correctly against the array. 

4530 

4531 Returns 

4532 ------- 

4533 result : ndarray or scalar 

4534 An array with the same shape as the input array, with the specified 

4535 axis removed. If the array is a 0-d array, or if `axis` is None, a 

4536 scalar is returned. 

4537 

4538 See Also 

4539 -------- 

4540 ma.count_masked : Count masked elements in array or along a given axis. 

4541 

4542 Examples 

4543 -------- 

4544 >>> import numpy.ma as ma 

4545 >>> a = ma.arange(6).reshape((2, 3)) 

4546 >>> a[1, :] = ma.masked 

4547 >>> a 

4548 masked_array( 

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

4550 [--, --, --]], 

4551 mask=[[False, False, False], 

4552 [ True, True, True]], 

4553 fill_value=999999) 

4554 >>> a.count() 

4555 3 

4556 

4557 When the `axis` keyword is specified an array of appropriate size is 

4558 returned. 

4559 

4560 >>> a.count(axis=0) 

4561 array([1, 1, 1]) 

4562 >>> a.count(axis=1) 

4563 array([3, 0]) 

4564 

4565 """ 

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

4567 

4568 m = self._mask 

4569 # special case for matrices (we assume no other subclasses modify 

4570 # their dimensions) 

4571 if isinstance(self.data, np.matrix): 

4572 if m is nomask: 

4573 m = np.zeros(self.shape, dtype=np.bool_) 

4574 m = m.view(type(self.data)) 

4575 

4576 if m is nomask: 

4577 # compare to _count_reduce_items in _methods.py 

4578 

4579 if self.shape == (): 

4580 if axis not in (None, 0): 

4581 raise np.AxisError(axis=axis, ndim=self.ndim) 

4582 return 1 

4583 elif axis is None: 

4584 if kwargs.get('keepdims', False): 

4585 return np.array(self.size, dtype=np.intp, ndmin=self.ndim) 

4586 return self.size 

4587 

4588 axes = normalize_axis_tuple(axis, self.ndim) 

4589 items = 1 

4590 for ax in axes: 

4591 items *= self.shape[ax] 

4592 

4593 if kwargs.get('keepdims', False): 

4594 out_dims = list(self.shape) 

4595 for a in axes: 

4596 out_dims[a] = 1 

4597 else: 

4598 out_dims = [d for n, d in enumerate(self.shape) 

4599 if n not in axes] 

4600 # make sure to return a 0-d array if axis is supplied 

4601 return np.full(out_dims, items, dtype=np.intp) 

4602 

4603 # take care of the masked singleton 

4604 if self is masked: 

4605 return 0 

4606 

4607 return (~m).sum(axis=axis, dtype=np.intp, **kwargs) 

4608 

4609 def ravel(self, order='C'): 

4610 """ 

4611 Returns a 1D version of self, as a view. 

4612 

4613 Parameters 

4614 ---------- 

4615 order : {'C', 'F', 'A', 'K'}, optional 

4616 The elements of `a` are read using this index order. 'C' means to 

4617 index the elements in C-like order, with the last axis index 

4618 changing fastest, back to the first axis index changing slowest. 

4619 'F' means to index the elements in Fortran-like index order, with 

4620 the first index changing fastest, and the last index changing 

4621 slowest. Note that the 'C' and 'F' options take no account of the 

4622 memory layout of the underlying array, and only refer to the order 

4623 of axis indexing. 'A' means to read the elements in Fortran-like 

4624 index order if `m` is Fortran *contiguous* in memory, C-like order 

4625 otherwise. 'K' means to read the elements in the order they occur 

4626 in memory, except for reversing the data when strides are negative. 

4627 By default, 'C' index order is used. 

4628 

4629 Returns 

4630 ------- 

4631 MaskedArray 

4632 Output view is of shape ``(self.size,)`` (or 

4633 ``(np.ma.product(self.shape),)``). 

4634 

4635 Examples 

4636 -------- 

4637 >>> x = np.ma.array([[1,2,3],[4,5,6],[7,8,9]], mask=[0] + [1,0]*4) 

4638 >>> x 

4639 masked_array( 

4640 data=[[1, --, 3], 

4641 [--, 5, --], 

4642 [7, --, 9]], 

4643 mask=[[False, True, False], 

4644 [ True, False, True], 

4645 [False, True, False]], 

4646 fill_value=999999) 

4647 >>> x.ravel() 

4648 masked_array(data=[1, --, 3, --, 5, --, 7, --, 9], 

4649 mask=[False, True, False, True, False, True, False, True, 

4650 False], 

4651 fill_value=999999) 

4652 

4653 """ 

4654 r = ndarray.ravel(self._data, order=order).view(type(self)) 

4655 r._update_from(self) 

4656 if self._mask is not nomask: 

4657 r._mask = ndarray.ravel(self._mask, order=order).reshape(r.shape) 

4658 else: 

4659 r._mask = nomask 

4660 return r 

4661 

4662 

4663 def reshape(self, *s, **kwargs): 

4664 """ 

4665 Give a new shape to the array without changing its data. 

4666 

4667 Returns a masked array containing the same data, but with a new shape. 

4668 The result is a view on the original array; if this is not possible, a 

4669 ValueError is raised. 

4670 

4671 Parameters 

4672 ---------- 

4673 shape : int or tuple of ints 

4674 The new shape should be compatible with the original shape. If an 

4675 integer is supplied, then the result will be a 1-D array of that 

4676 length. 

4677 order : {'C', 'F'}, optional 

4678 Determines whether the array data should be viewed as in C 

4679 (row-major) or FORTRAN (column-major) order. 

4680 

4681 Returns 

4682 ------- 

4683 reshaped_array : array 

4684 A new view on the array. 

4685 

4686 See Also 

4687 -------- 

4688 reshape : Equivalent function in the masked array module. 

4689 numpy.ndarray.reshape : Equivalent method on ndarray object. 

4690 numpy.reshape : Equivalent function in the NumPy module. 

4691 

4692 Notes 

4693 ----- 

4694 The reshaping operation cannot guarantee that a copy will not be made, 

4695 to modify the shape in place, use ``a.shape = s`` 

4696 

4697 Examples 

4698 -------- 

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

4700 >>> x 

4701 masked_array( 

4702 data=[[--, 2], 

4703 [3, --]], 

4704 mask=[[ True, False], 

4705 [False, True]], 

4706 fill_value=999999) 

4707 >>> x = x.reshape((4,1)) 

4708 >>> x 

4709 masked_array( 

4710 data=[[--], 

4711 [2], 

4712 [3], 

4713 [--]], 

4714 mask=[[ True], 

4715 [False], 

4716 [False], 

4717 [ True]], 

4718 fill_value=999999) 

4719 

4720 """ 

4721 kwargs.update(order=kwargs.get('order', 'C')) 

4722 result = self._data.reshape(*s, **kwargs).view(type(self)) 

4723 result._update_from(self) 

4724 mask = self._mask 

4725 if mask is not nomask: 

4726 result._mask = mask.reshape(*s, **kwargs) 

4727 return result 

4728 

4729 def resize(self, newshape, refcheck=True, order=False): 

4730 """ 

4731 .. warning:: 

4732 

4733 This method does nothing, except raise a ValueError exception. A 

4734 masked array does not own its data and therefore cannot safely be 

4735 resized in place. Use the `numpy.ma.resize` function instead. 

4736 

4737 This method is difficult to implement safely and may be deprecated in 

4738 future releases of NumPy. 

4739 

4740 """ 

4741 # Note : the 'order' keyword looks broken, let's just drop it 

4742 errmsg = "A masked array does not own its data "\ 

4743 "and therefore cannot be resized.\n" \ 

4744 "Use the numpy.ma.resize function instead." 

4745 raise ValueError(errmsg) 

4746 

4747 def put(self, indices, values, mode='raise'): 

4748 """ 

4749 Set storage-indexed locations to corresponding values. 

4750 

4751 Sets self._data.flat[n] = values[n] for each n in indices. 

4752 If `values` is shorter than `indices` then it will repeat. 

4753 If `values` has some masked values, the initial mask is updated 

4754 in consequence, else the corresponding values are unmasked. 

4755 

4756 Parameters 

4757 ---------- 

4758 indices : 1-D array_like 

4759 Target indices, interpreted as integers. 

4760 values : array_like 

4761 Values to place in self._data copy at target indices. 

4762 mode : {'raise', 'wrap', 'clip'}, optional 

4763 Specifies how out-of-bounds indices will behave. 

4764 'raise' : raise an error. 

4765 'wrap' : wrap around. 

4766 'clip' : clip to the range. 

4767 

4768 Notes 

4769 ----- 

4770 `values` can be a scalar or length 1 array. 

4771 

4772 Examples 

4773 -------- 

4774 >>> x = np.ma.array([[1,2,3],[4,5,6],[7,8,9]], mask=[0] + [1,0]*4) 

4775 >>> x 

4776 masked_array( 

4777 data=[[1, --, 3], 

4778 [--, 5, --], 

4779 [7, --, 9]], 

4780 mask=[[False, True, False], 

4781 [ True, False, True], 

4782 [False, True, False]], 

4783 fill_value=999999) 

4784 >>> x.put([0,4,8],[10,20,30]) 

4785 >>> x 

4786 masked_array( 

4787 data=[[10, --, 3], 

4788 [--, 20, --], 

4789 [7, --, 30]], 

4790 mask=[[False, True, False], 

4791 [ True, False, True], 

4792 [False, True, False]], 

4793 fill_value=999999) 

4794 

4795 >>> x.put(4,999) 

4796 >>> x 

4797 masked_array( 

4798 data=[[10, --, 3], 

4799 [--, 999, --], 

4800 [7, --, 30]], 

4801 mask=[[False, True, False], 

4802 [ True, False, True], 

4803 [False, True, False]], 

4804 fill_value=999999) 

4805 

4806 """ 

4807 # Hard mask: Get rid of the values/indices that fall on masked data 

4808 if self._hardmask and self._mask is not nomask: 

4809 mask = self._mask[indices] 

4810 indices = narray(indices, copy=False) 

4811 values = narray(values, copy=False, subok=True) 

4812 values.resize(indices.shape) 

4813 indices = indices[~mask] 

4814 values = values[~mask] 

4815 

4816 self._data.put(indices, values, mode=mode) 

4817 

4818 # short circuit if neither self nor values are masked 

4819 if self._mask is nomask and getmask(values) is nomask: 

4820 return 

4821 

4822 m = getmaskarray(self) 

4823 

4824 if getmask(values) is nomask: 

4825 m.put(indices, False, mode=mode) 

4826 else: 

4827 m.put(indices, values._mask, mode=mode) 

4828 m = make_mask(m, copy=False, shrink=True) 

4829 self._mask = m 

4830 return 

4831 

4832 def ids(self): 

4833 """ 

4834 Return the addresses of the data and mask areas. 

4835 

4836 Parameters 

4837 ---------- 

4838 None 

4839 

4840 Examples 

4841 -------- 

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

4843 >>> x.ids() 

4844 (166670640, 166659832) # may vary 

4845 

4846 If the array has no mask, the address of `nomask` is returned. This address 

4847 is typically not close to the data in memory: 

4848 

4849 >>> x = np.ma.array([1, 2, 3]) 

4850 >>> x.ids() 

4851 (166691080, 3083169284) # may vary 

4852 

4853 """ 

4854 if self._mask is nomask: 

4855 return (self.ctypes.data, id(nomask)) 

4856 return (self.ctypes.data, self._mask.ctypes.data) 

4857 

4858 def iscontiguous(self): 

4859 """ 

4860 Return a boolean indicating whether the data is contiguous. 

4861 

4862 Parameters 

4863 ---------- 

4864 None 

4865 

4866 Examples 

4867 -------- 

4868 >>> x = np.ma.array([1, 2, 3]) 

4869 >>> x.iscontiguous() 

4870 True 

4871 

4872 `iscontiguous` returns one of the flags of the masked array: 

4873 

4874 >>> x.flags 

4875 C_CONTIGUOUS : True 

4876 F_CONTIGUOUS : True 

4877 OWNDATA : False 

4878 WRITEABLE : True 

4879 ALIGNED : True 

4880 WRITEBACKIFCOPY : False 

4881 

4882 """ 

4883 return self.flags['CONTIGUOUS'] 

4884 

4885 def all(self, axis=None, out=None, keepdims=np._NoValue): 

4886 """ 

4887 Returns True if all elements evaluate to True. 

4888 

4889 The output array is masked where all the values along the given axis 

4890 are masked: if the output would have been a scalar and that all the 

4891 values are masked, then the output is `masked`. 

4892 

4893 Refer to `numpy.all` for full documentation. 

4894 

4895 See Also 

4896 -------- 

4897 numpy.ndarray.all : corresponding function for ndarrays 

4898 numpy.all : equivalent function 

4899 

4900 Examples 

4901 -------- 

4902 >>> np.ma.array([1,2,3]).all() 

4903 True 

4904 >>> a = np.ma.array([1,2,3], mask=True) 

4905 >>> (a.all() is np.ma.masked) 

4906 True 

4907 

4908 """ 

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

4910 

4911 mask = _check_mask_axis(self._mask, axis, **kwargs) 

4912 if out is None: 

4913 d = self.filled(True).all(axis=axis, **kwargs).view(type(self)) 

4914 if d.ndim: 

4915 d.__setmask__(mask) 

4916 elif mask: 

4917 return masked 

4918 return d 

4919 self.filled(True).all(axis=axis, out=out, **kwargs) 

4920 if isinstance(out, MaskedArray): 

4921 if out.ndim or mask: 

4922 out.__setmask__(mask) 

4923 return out 

4924 

4925 def any(self, axis=None, out=None, keepdims=np._NoValue): 

4926 """ 

4927 Returns True if any of the elements of `a` evaluate to True. 

4928 

4929 Masked values are considered as False during computation. 

4930 

4931 Refer to `numpy.any` for full documentation. 

4932 

4933 See Also 

4934 -------- 

4935 numpy.ndarray.any : corresponding function for ndarrays 

4936 numpy.any : equivalent function 

4937 

4938 """ 

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

4940 

4941 mask = _check_mask_axis(self._mask, axis, **kwargs) 

4942 if out is None: 

4943 d = self.filled(False).any(axis=axis, **kwargs).view(type(self)) 

4944 if d.ndim: 

4945 d.__setmask__(mask) 

4946 elif mask: 

4947 d = masked 

4948 return d 

4949 self.filled(False).any(axis=axis, out=out, **kwargs) 

4950 if isinstance(out, MaskedArray): 

4951 if out.ndim or mask: 

4952 out.__setmask__(mask) 

4953 return out 

4954 

4955 def nonzero(self): 

4956 """ 

4957 Return the indices of unmasked elements that are not zero. 

4958 

4959 Returns a tuple of arrays, one for each dimension, containing the 

4960 indices of the non-zero elements in that dimension. The corresponding 

4961 non-zero values can be obtained with:: 

4962 

4963 a[a.nonzero()] 

4964 

4965 To group the indices by element, rather than dimension, use 

4966 instead:: 

4967 

4968 np.transpose(a.nonzero()) 

4969 

4970 The result of this is always a 2d array, with a row for each non-zero 

4971 element. 

4972 

4973 Parameters 

4974 ---------- 

4975 None 

4976 

4977 Returns 

4978 ------- 

4979 tuple_of_arrays : tuple 

4980 Indices of elements that are non-zero. 

4981 

4982 See Also 

4983 -------- 

4984 numpy.nonzero : 

4985 Function operating on ndarrays. 

4986 flatnonzero : 

4987 Return indices that are non-zero in the flattened version of the input 

4988 array. 

4989 numpy.ndarray.nonzero : 

4990 Equivalent ndarray method. 

4991 count_nonzero : 

4992 Counts the number of non-zero elements in the input array. 

4993 

4994 Examples 

4995 -------- 

4996 >>> import numpy.ma as ma 

4997 >>> x = ma.array(np.eye(3)) 

4998 >>> x 

4999 masked_array( 

5000 data=[[1., 0., 0.], 

5001 [0., 1., 0.], 

5002 [0., 0., 1.]], 

5003 mask=False, 

5004 fill_value=1e+20) 

5005 >>> x.nonzero() 

5006 (array([0, 1, 2]), array([0, 1, 2])) 

5007 

5008 Masked elements are ignored. 

5009 

5010 >>> x[1, 1] = ma.masked 

5011 >>> x 

5012 masked_array( 

5013 data=[[1.0, 0.0, 0.0], 

5014 [0.0, --, 0.0], 

5015 [0.0, 0.0, 1.0]], 

5016 mask=[[False, False, False], 

5017 [False, True, False], 

5018 [False, False, False]], 

5019 fill_value=1e+20) 

5020 >>> x.nonzero() 

5021 (array([0, 2]), array([0, 2])) 

5022 

5023 Indices can also be grouped by element. 

5024 

5025 >>> np.transpose(x.nonzero()) 

5026 array([[0, 0], 

5027 [2, 2]]) 

5028 

5029 A common use for ``nonzero`` is to find the indices of an array, where 

5030 a condition is True. Given an array `a`, the condition `a` > 3 is a 

5031 boolean array and since False is interpreted as 0, ma.nonzero(a > 3) 

5032 yields the indices of the `a` where the condition is true. 

5033 

5034 >>> a = ma.array([[1,2,3],[4,5,6],[7,8,9]]) 

5035 >>> a > 3 

5036 masked_array( 

5037 data=[[False, False, False], 

5038 [ True, True, True], 

5039 [ True, True, True]], 

5040 mask=False, 

5041 fill_value=True) 

5042 >>> ma.nonzero(a > 3) 

5043 (array([1, 1, 1, 2, 2, 2]), array([0, 1, 2, 0, 1, 2])) 

5044 

5045 The ``nonzero`` method of the condition array can also be called. 

5046 

5047 >>> (a > 3).nonzero() 

5048 (array([1, 1, 1, 2, 2, 2]), array([0, 1, 2, 0, 1, 2])) 

5049 

5050 """ 

5051 return narray(self.filled(0), copy=False).nonzero() 

5052 

5053 def trace(self, offset=0, axis1=0, axis2=1, dtype=None, out=None): 

5054 """ 

5055 (this docstring should be overwritten) 

5056 """ 

5057 #!!!: implement out + test! 

5058 m = self._mask 

5059 if m is nomask: 

5060 result = super().trace(offset=offset, axis1=axis1, axis2=axis2, 

5061 out=out) 

5062 return result.astype(dtype) 

5063 else: 

5064 D = self.diagonal(offset=offset, axis1=axis1, axis2=axis2) 

5065 return D.astype(dtype).filled(0).sum(axis=-1, out=out) 

5066 trace.__doc__ = ndarray.trace.__doc__ 

5067 

5068 def dot(self, b, out=None, strict=False): 

5069 """ 

5070 a.dot(b, out=None) 

5071 

5072 Masked dot product of two arrays. Note that `out` and `strict` are 

5073 located in different positions than in `ma.dot`. In order to 

5074 maintain compatibility with the functional version, it is 

5075 recommended that the optional arguments be treated as keyword only. 

5076 At some point that may be mandatory. 

5077 

5078 .. versionadded:: 1.10.0 

5079 

5080 Parameters 

5081 ---------- 

5082 b : masked_array_like 

5083 Inputs array. 

5084 out : masked_array, optional 

5085 Output argument. This must have the exact kind that would be 

5086 returned if it was not used. In particular, it must have the 

5087 right type, must be C-contiguous, and its dtype must be the 

5088 dtype that would be returned for `ma.dot(a,b)`. This is a 

5089 performance feature. Therefore, if these conditions are not 

5090 met, an exception is raised, instead of attempting to be 

5091 flexible. 

5092 strict : bool, optional 

5093 Whether masked data are propagated (True) or set to 0 (False) 

5094 for the computation. Default is False. Propagating the mask 

5095 means that if a masked value appears in a row or column, the 

5096 whole row or column is considered masked. 

5097 

5098 .. versionadded:: 1.10.2 

5099 

5100 See Also 

5101 -------- 

5102 numpy.ma.dot : equivalent function 

5103 

5104 """ 

5105 return dot(self, b, out=out, strict=strict) 

5106 

5107 def sum(self, axis=None, dtype=None, out=None, keepdims=np._NoValue): 

5108 """ 

5109 Return the sum of the array elements over the given axis. 

5110 

5111 Masked elements are set to 0 internally. 

5112 

5113 Refer to `numpy.sum` for full documentation. 

5114 

5115 See Also 

5116 -------- 

5117 numpy.ndarray.sum : corresponding function for ndarrays 

5118 numpy.sum : equivalent function 

5119 

5120 Examples 

5121 -------- 

5122 >>> x = np.ma.array([[1,2,3],[4,5,6],[7,8,9]], mask=[0] + [1,0]*4) 

5123 >>> x 

5124 masked_array( 

5125 data=[[1, --, 3], 

5126 [--, 5, --], 

5127 [7, --, 9]], 

5128 mask=[[False, True, False], 

5129 [ True, False, True], 

5130 [False, True, False]], 

5131 fill_value=999999) 

5132 >>> x.sum() 

5133 25 

5134 >>> x.sum(axis=1) 

5135 masked_array(data=[4, 5, 16], 

5136 mask=[False, False, False], 

5137 fill_value=999999) 

5138 >>> x.sum(axis=0) 

5139 masked_array(data=[8, 5, 12], 

5140 mask=[False, False, False], 

5141 fill_value=999999) 

5142 >>> print(type(x.sum(axis=0, dtype=np.int64)[0])) 

5143 <class 'numpy.int64'> 

5144 

5145 """ 

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

5147 

5148 _mask = self._mask 

5149 newmask = _check_mask_axis(_mask, axis, **kwargs) 

5150 # No explicit output 

5151 if out is None: 

5152 result = self.filled(0).sum(axis, dtype=dtype, **kwargs) 

5153 rndim = getattr(result, 'ndim', 0) 

5154 if rndim: 

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

5156 result.__setmask__(newmask) 

5157 elif newmask: 

5158 result = masked 

5159 return result 

5160 # Explicit output 

5161 result = self.filled(0).sum(axis, dtype=dtype, out=out, **kwargs) 

5162 if isinstance(out, MaskedArray): 

5163 outmask = getmask(out) 

5164 if outmask is nomask: 

5165 outmask = out._mask = make_mask_none(out.shape) 

5166 outmask.flat = newmask 

5167 return out 

5168 

5169 def cumsum(self, axis=None, dtype=None, out=None): 

5170 """ 

5171 Return the cumulative sum of the array elements over the given axis. 

5172 

5173 Masked values are set to 0 internally during the computation. 

5174 However, their position is saved, and the result will be masked at 

5175 the same locations. 

5176 

5177 Refer to `numpy.cumsum` for full documentation. 

5178 

5179 Notes 

5180 ----- 

5181 The mask is lost if `out` is not a valid :class:`ma.MaskedArray` ! 

5182 

5183 Arithmetic is modular when using integer types, and no error is 

5184 raised on overflow. 

5185 

5186 See Also 

5187 -------- 

5188 numpy.ndarray.cumsum : corresponding function for ndarrays 

5189 numpy.cumsum : equivalent function 

5190 

5191 Examples 

5192 -------- 

5193 >>> marr = np.ma.array(np.arange(10), mask=[0,0,0,1,1,1,0,0,0,0]) 

5194 >>> marr.cumsum() 

5195 masked_array(data=[0, 1, 3, --, --, --, 9, 16, 24, 33], 

5196 mask=[False, False, False, True, True, True, False, False, 

5197 False, False], 

5198 fill_value=999999) 

5199 

5200 """ 

5201 result = self.filled(0).cumsum(axis=axis, dtype=dtype, out=out) 

5202 if out is not None: 

5203 if isinstance(out, MaskedArray): 

5204 out.__setmask__(self.mask) 

5205 return out 

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

5207 result.__setmask__(self._mask) 

5208 return result 

5209 

5210 def prod(self, axis=None, dtype=None, out=None, keepdims=np._NoValue): 

5211 """ 

5212 Return the product of the array elements over the given axis. 

5213 

5214 Masked elements are set to 1 internally for computation. 

5215 

5216 Refer to `numpy.prod` for full documentation. 

5217 

5218 Notes 

5219 ----- 

5220 Arithmetic is modular when using integer types, and no error is raised 

5221 on overflow. 

5222 

5223 See Also 

5224 -------- 

5225 numpy.ndarray.prod : corresponding function for ndarrays 

5226 numpy.prod : equivalent function 

5227 """ 

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

5229 

5230 _mask = self._mask 

5231 newmask = _check_mask_axis(_mask, axis, **kwargs) 

5232 # No explicit output 

5233 if out is None: 

5234 result = self.filled(1).prod(axis, dtype=dtype, **kwargs) 

5235 rndim = getattr(result, 'ndim', 0) 

5236 if rndim: 

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

5238 result.__setmask__(newmask) 

5239 elif newmask: 

5240 result = masked 

5241 return result 

5242 # Explicit output 

5243 result = self.filled(1).prod(axis, dtype=dtype, out=out, **kwargs) 

5244 if isinstance(out, MaskedArray): 

5245 outmask = getmask(out) 

5246 if outmask is nomask: 

5247 outmask = out._mask = make_mask_none(out.shape) 

5248 outmask.flat = newmask 

5249 return out 

5250 product = prod 

5251 

5252 def cumprod(self, axis=None, dtype=None, out=None): 

5253 """ 

5254 Return the cumulative product of the array elements over the given axis. 

5255 

5256 Masked values are set to 1 internally during the computation. 

5257 However, their position is saved, and the result will be masked at 

5258 the same locations. 

5259 

5260 Refer to `numpy.cumprod` for full documentation. 

5261 

5262 Notes 

5263 ----- 

5264 The mask is lost if `out` is not a valid MaskedArray ! 

5265 

5266 Arithmetic is modular when using integer types, and no error is 

5267 raised on overflow. 

5268 

5269 See Also 

5270 -------- 

5271 numpy.ndarray.cumprod : corresponding function for ndarrays 

5272 numpy.cumprod : equivalent function 

5273 """ 

5274 result = self.filled(1).cumprod(axis=axis, dtype=dtype, out=out) 

5275 if out is not None: 

5276 if isinstance(out, MaskedArray): 

5277 out.__setmask__(self._mask) 

5278 return out 

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

5280 result.__setmask__(self._mask) 

5281 return result 

5282 

5283 def mean(self, axis=None, dtype=None, out=None, keepdims=np._NoValue): 

5284 """ 

5285 Returns the average of the array elements along given axis. 

5286 

5287 Masked entries are ignored, and result elements which are not 

5288 finite will be masked. 

5289 

5290 Refer to `numpy.mean` for full documentation. 

5291 

5292 See Also 

5293 -------- 

5294 numpy.ndarray.mean : corresponding function for ndarrays 

5295 numpy.mean : Equivalent function 

5296 numpy.ma.average : Weighted average. 

5297 

5298 Examples 

5299 -------- 

5300 >>> a = np.ma.array([1,2,3], mask=[False, False, True]) 

5301 >>> a 

5302 masked_array(data=[1, 2, --], 

5303 mask=[False, False, True], 

5304 fill_value=999999) 

5305 >>> a.mean() 

5306 1.5 

5307 

5308 """ 

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

5310 if self._mask is nomask: 

5311 result = super().mean(axis=axis, dtype=dtype, **kwargs)[()] 

5312 else: 

5313 is_float16_result = False 

5314 if dtype is None: 

5315 if issubclass(self.dtype.type, (ntypes.integer, ntypes.bool_)): 

5316 dtype = mu.dtype('f8') 

5317 elif issubclass(self.dtype.type, ntypes.float16): 

5318 dtype = mu.dtype('f4') 

5319 is_float16_result = True 

5320 dsum = self.sum(axis=axis, dtype=dtype, **kwargs) 

5321 cnt = self.count(axis=axis, **kwargs) 

5322 if cnt.shape == () and (cnt == 0): 

5323 result = masked 

5324 elif is_float16_result: 

5325 result = self.dtype.type(dsum * 1. / cnt) 

5326 else: 

5327 result = dsum * 1. / cnt 

5328 if out is not None: 

5329 out.flat = result 

5330 if isinstance(out, MaskedArray): 

5331 outmask = getmask(out) 

5332 if outmask is nomask: 

5333 outmask = out._mask = make_mask_none(out.shape) 

5334 outmask.flat = getmask(result) 

5335 return out 

5336 return result 

5337 

5338 def anom(self, axis=None, dtype=None): 

5339 """ 

5340 Compute the anomalies (deviations from the arithmetic mean) 

5341 along the given axis. 

5342 

5343 Returns an array of anomalies, with the same shape as the input and 

5344 where the arithmetic mean is computed along the given axis. 

5345 

5346 Parameters 

5347 ---------- 

5348 axis : int, optional 

5349 Axis over which the anomalies are taken. 

5350 The default is to use the mean of the flattened array as reference. 

5351 dtype : dtype, optional 

5352 Type to use in computing the variance. For arrays of integer type 

5353 the default is float32; for arrays of float types it is the same as 

5354 the array type. 

5355 

5356 See Also 

5357 -------- 

5358 mean : Compute the mean of the array. 

5359 

5360 Examples 

5361 -------- 

5362 >>> a = np.ma.array([1,2,3]) 

5363 >>> a.anom() 

5364 masked_array(data=[-1., 0., 1.], 

5365 mask=False, 

5366 fill_value=1e+20) 

5367 

5368 """ 

5369 m = self.mean(axis, dtype) 

5370 if not axis: 

5371 return self - m 

5372 else: 

5373 return self - expand_dims(m, axis) 

5374 

5375 def var(self, axis=None, dtype=None, out=None, ddof=0, 

5376 keepdims=np._NoValue): 

5377 """ 

5378 Returns the variance of the array elements along given axis. 

5379 

5380 Masked entries are ignored, and result elements which are not 

5381 finite will be masked. 

5382 

5383 Refer to `numpy.var` for full documentation. 

5384 

5385 See Also 

5386 -------- 

5387 numpy.ndarray.var : corresponding function for ndarrays 

5388 numpy.var : Equivalent function 

5389 """ 

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

5391 

5392 # Easy case: nomask, business as usual 

5393 if self._mask is nomask: 

5394 ret = super().var(axis=axis, dtype=dtype, out=out, ddof=ddof, 

5395 **kwargs)[()] 

5396 if out is not None: 

5397 if isinstance(out, MaskedArray): 

5398 out.__setmask__(nomask) 

5399 return out 

5400 return ret 

5401 

5402 # Some data are masked, yay! 

5403 cnt = self.count(axis=axis, **kwargs) - ddof 

5404 danom = self - self.mean(axis, dtype, keepdims=True) 

5405 if iscomplexobj(self): 

5406 danom = umath.absolute(danom) ** 2 

5407 else: 

5408 danom *= danom 

5409 dvar = divide(danom.sum(axis, **kwargs), cnt).view(type(self)) 

5410 # Apply the mask if it's not a scalar 

5411 if dvar.ndim: 

5412 dvar._mask = mask_or(self._mask.all(axis, **kwargs), (cnt <= 0)) 

5413 dvar._update_from(self) 

5414 elif getmask(dvar): 

5415 # Make sure that masked is returned when the scalar is masked. 

5416 dvar = masked 

5417 if out is not None: 

5418 if isinstance(out, MaskedArray): 

5419 out.flat = 0 

5420 out.__setmask__(True) 

5421 elif out.dtype.kind in 'biu': 

5422 errmsg = "Masked data information would be lost in one or "\ 

5423 "more location." 

5424 raise MaskError(errmsg) 

5425 else: 

5426 out.flat = np.nan 

5427 return out 

5428 # In case with have an explicit output 

5429 if out is not None: 

5430 # Set the data 

5431 out.flat = dvar 

5432 # Set the mask if needed 

5433 if isinstance(out, MaskedArray): 

5434 out.__setmask__(dvar.mask) 

5435 return out 

5436 return dvar 

5437 var.__doc__ = np.var.__doc__ 

5438 

5439 def std(self, axis=None, dtype=None, out=None, ddof=0, 

5440 keepdims=np._NoValue): 

5441 """ 

5442 Returns the standard deviation of the array elements along given axis. 

5443 

5444 Masked entries are ignored. 

5445 

5446 Refer to `numpy.std` for full documentation. 

5447 

5448 See Also 

5449 -------- 

5450 numpy.ndarray.std : corresponding function for ndarrays 

5451 numpy.std : Equivalent function 

5452 """ 

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

5454 

5455 dvar = self.var(axis, dtype, out, ddof, **kwargs) 

5456 if dvar is not masked: 

5457 if out is not None: 

5458 np.power(out, 0.5, out=out, casting='unsafe') 

5459 return out 

5460 dvar = sqrt(dvar) 

5461 return dvar 

5462 

5463 def round(self, decimals=0, out=None): 

5464 """ 

5465 Return each element rounded to the given number of decimals. 

5466 

5467 Refer to `numpy.around` for full documentation. 

5468 

5469 See Also 

5470 -------- 

5471 numpy.ndarray.round : corresponding function for ndarrays 

5472 numpy.around : equivalent function 

5473 """ 

5474 result = self._data.round(decimals=decimals, out=out).view(type(self)) 

5475 if result.ndim > 0: 

5476 result._mask = self._mask 

5477 result._update_from(self) 

5478 elif self._mask: 

5479 # Return masked when the scalar is masked 

5480 result = masked 

5481 # No explicit output: we're done 

5482 if out is None: 

5483 return result 

5484 if isinstance(out, MaskedArray): 

5485 out.__setmask__(self._mask) 

5486 return out 

5487 

5488 def argsort(self, axis=np._NoValue, kind=None, order=None, 

5489 endwith=True, fill_value=None): 

5490 """ 

5491 Return an ndarray of indices that sort the array along the 

5492 specified axis. Masked values are filled beforehand to 

5493 `fill_value`. 

5494 

5495 Parameters 

5496 ---------- 

5497 axis : int, optional 

5498 Axis along which to sort. If None, the default, the flattened array 

5499 is used. 

5500 

5501 .. versionchanged:: 1.13.0 

5502 Previously, the default was documented to be -1, but that was 

5503 in error. At some future date, the default will change to -1, as 

5504 originally intended. 

5505 Until then, the axis should be given explicitly when 

5506 ``arr.ndim > 1``, to avoid a FutureWarning. 

5507 kind : {'quicksort', 'mergesort', 'heapsort', 'stable'}, optional 

5508 The sorting algorithm used. 

5509 order : list, optional 

5510 When `a` is an array with fields defined, this argument specifies 

5511 which fields to compare first, second, etc. Not all fields need be 

5512 specified. 

5513 endwith : {True, False}, optional 

5514 Whether missing values (if any) should be treated as the largest values 

5515 (True) or the smallest values (False) 

5516 When the array contains unmasked values at the same extremes of the 

5517 datatype, the ordering of these values and the masked values is 

5518 undefined. 

5519 fill_value : scalar or None, optional 

5520 Value used internally for the masked values. 

5521 If ``fill_value`` is not None, it supersedes ``endwith``. 

5522 

5523 Returns 

5524 ------- 

5525 index_array : ndarray, int 

5526 Array of indices that sort `a` along the specified axis. 

5527 In other words, ``a[index_array]`` yields a sorted `a`. 

5528 

5529 See Also 

5530 -------- 

5531 ma.MaskedArray.sort : Describes sorting algorithms used. 

5532 lexsort : Indirect stable sort with multiple keys. 

5533 numpy.ndarray.sort : Inplace sort. 

5534 

5535 Notes 

5536 ----- 

5537 See `sort` for notes on the different sorting algorithms. 

5538 

5539 Examples 

5540 -------- 

5541 >>> a = np.ma.array([3,2,1], mask=[False, False, True]) 

5542 >>> a 

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

5544 mask=[False, False, True], 

5545 fill_value=999999) 

5546 >>> a.argsort() 

5547 array([1, 0, 2]) 

5548 

5549 """ 

5550 

5551 # 2017-04-11, Numpy 1.13.0, gh-8701: warn on axis default 

5552 if axis is np._NoValue: 

5553 axis = _deprecate_argsort_axis(self) 

5554 

5555 if fill_value is None: 

5556 if endwith: 

5557 # nan > inf 

5558 if np.issubdtype(self.dtype, np.floating): 

5559 fill_value = np.nan 

5560 else: 

5561 fill_value = minimum_fill_value(self) 

5562 else: 

5563 fill_value = maximum_fill_value(self) 

5564 

5565 filled = self.filled(fill_value) 

5566 return filled.argsort(axis=axis, kind=kind, order=order) 

5567 

5568 def argmin(self, axis=None, fill_value=None, out=None, *, 

5569 keepdims=np._NoValue): 

5570 """ 

5571 Return array of indices to the minimum values along the given axis. 

5572 

5573 Parameters 

5574 ---------- 

5575 axis : {None, integer} 

5576 If None, the index is into the flattened array, otherwise along 

5577 the specified axis 

5578 fill_value : scalar or None, optional 

5579 Value used to fill in the masked values. If None, the output of 

5580 minimum_fill_value(self._data) is used instead. 

5581 out : {None, array}, optional 

5582 Array into which the result can be placed. Its type is preserved 

5583 and it must be of the right shape to hold the output. 

5584 

5585 Returns 

5586 ------- 

5587 ndarray or scalar 

5588 If multi-dimension input, returns a new ndarray of indices to the 

5589 minimum values along the given axis. Otherwise, returns a scalar 

5590 of index to the minimum values along the given axis. 

5591 

5592 Examples 

5593 -------- 

5594 >>> x = np.ma.array(np.arange(4), mask=[1,1,0,0]) 

5595 >>> x.shape = (2,2) 

5596 >>> x 

5597 masked_array( 

5598 data=[[--, --], 

5599 [2, 3]], 

5600 mask=[[ True, True], 

5601 [False, False]], 

5602 fill_value=999999) 

5603 >>> x.argmin(axis=0, fill_value=-1) 

5604 array([0, 0]) 

5605 >>> x.argmin(axis=0, fill_value=9) 

5606 array([1, 1]) 

5607 

5608 """ 

5609 if fill_value is None: 

5610 fill_value = minimum_fill_value(self) 

5611 d = self.filled(fill_value).view(ndarray) 

5612 keepdims = False if keepdims is np._NoValue else bool(keepdims) 

5613 return d.argmin(axis, out=out, keepdims=keepdims) 

5614 

5615 def argmax(self, axis=None, fill_value=None, out=None, *, 

5616 keepdims=np._NoValue): 

5617 """ 

5618 Returns array of indices of the maximum values along the given axis. 

5619 Masked values are treated as if they had the value fill_value. 

5620 

5621 Parameters 

5622 ---------- 

5623 axis : {None, integer} 

5624 If None, the index is into the flattened array, otherwise along 

5625 the specified axis 

5626 fill_value : scalar or None, optional 

5627 Value used to fill in the masked values. If None, the output of 

5628 maximum_fill_value(self._data) is used instead. 

5629 out : {None, array}, optional 

5630 Array into which the result can be placed. Its type is preserved 

5631 and it must be of the right shape to hold the output. 

5632 

5633 Returns 

5634 ------- 

5635 index_array : {integer_array} 

5636 

5637 Examples 

5638 -------- 

5639 >>> a = np.arange(6).reshape(2,3) 

5640 >>> a.argmax() 

5641 5 

5642 >>> a.argmax(0) 

5643 array([1, 1, 1]) 

5644 >>> a.argmax(1) 

5645 array([2, 2]) 

5646 

5647 """ 

5648 if fill_value is None: 

5649 fill_value = maximum_fill_value(self._data) 

5650 d = self.filled(fill_value).view(ndarray) 

5651 keepdims = False if keepdims is np._NoValue else bool(keepdims) 

5652 return d.argmax(axis, out=out, keepdims=keepdims) 

5653 

5654 def sort(self, axis=-1, kind=None, order=None, 

5655 endwith=True, fill_value=None): 

5656 """ 

5657 Sort the array, in-place 

5658 

5659 Parameters 

5660 ---------- 

5661 a : array_like 

5662 Array to be sorted. 

5663 axis : int, optional 

5664 Axis along which to sort. If None, the array is flattened before 

5665 sorting. The default is -1, which sorts along the last axis. 

5666 kind : {'quicksort', 'mergesort', 'heapsort', 'stable'}, optional 

5667 The sorting algorithm used. 

5668 order : list, optional 

5669 When `a` is a structured array, this argument specifies which fields 

5670 to compare first, second, and so on. This list does not need to 

5671 include all of the fields. 

5672 endwith : {True, False}, optional 

5673 Whether missing values (if any) should be treated as the largest values 

5674 (True) or the smallest values (False) 

5675 When the array contains unmasked values sorting at the same extremes of the 

5676 datatype, the ordering of these values and the masked values is 

5677 undefined. 

5678 fill_value : scalar or None, optional 

5679 Value used internally for the masked values. 

5680 If ``fill_value`` is not None, it supersedes ``endwith``. 

5681 

5682 Returns 

5683 ------- 

5684 sorted_array : ndarray 

5685 Array of the same type and shape as `a`. 

5686 

5687 See Also 

5688 -------- 

5689 numpy.ndarray.sort : Method to sort an array in-place. 

5690 argsort : Indirect sort. 

5691 lexsort : Indirect stable sort on multiple keys. 

5692 searchsorted : Find elements in a sorted array. 

5693 

5694 Notes 

5695 ----- 

5696 See ``sort`` for notes on the different sorting algorithms. 

5697 

5698 Examples 

5699 -------- 

5700 >>> a = np.ma.array([1, 2, 5, 4, 3],mask=[0, 1, 0, 1, 0]) 

5701 >>> # Default 

5702 >>> a.sort() 

5703 >>> a 

5704 masked_array(data=[1, 3, 5, --, --], 

5705 mask=[False, False, False, True, True], 

5706 fill_value=999999) 

5707 

5708 >>> a = np.ma.array([1, 2, 5, 4, 3],mask=[0, 1, 0, 1, 0]) 

5709 >>> # Put missing values in the front 

5710 >>> a.sort(endwith=False) 

5711 >>> a 

5712 masked_array(data=[--, --, 1, 3, 5], 

5713 mask=[ True, True, False, False, False], 

5714 fill_value=999999) 

5715 

5716 >>> a = np.ma.array([1, 2, 5, 4, 3],mask=[0, 1, 0, 1, 0]) 

5717 >>> # fill_value takes over endwith 

5718 >>> a.sort(endwith=False, fill_value=3) 

5719 >>> a 

5720 masked_array(data=[1, --, --, 3, 5], 

5721 mask=[False, True, True, False, False], 

5722 fill_value=999999) 

5723 

5724 """ 

5725 if self._mask is nomask: 

5726 ndarray.sort(self, axis=axis, kind=kind, order=order) 

5727 return 

5728 

5729 if self is masked: 

5730 return 

5731 

5732 sidx = self.argsort(axis=axis, kind=kind, order=order, 

5733 fill_value=fill_value, endwith=endwith) 

5734 

5735 self[...] = np.take_along_axis(self, sidx, axis=axis) 

5736 

5737 def min(self, axis=None, out=None, fill_value=None, keepdims=np._NoValue): 

5738 """ 

5739 Return the minimum along a given axis. 

5740 

5741 Parameters 

5742 ---------- 

5743 axis : None or int or tuple of ints, optional 

5744 Axis along which to operate. By default, ``axis`` is None and the 

5745 flattened input is used. 

5746 .. versionadded:: 1.7.0 

5747 If this is a tuple of ints, the minimum is selected over multiple 

5748 axes, instead of a single axis or all the axes as before. 

5749 out : array_like, optional 

5750 Alternative output array in which to place the result. Must be of 

5751 the same shape and buffer length as the expected output. 

5752 fill_value : scalar or None, optional 

5753 Value used to fill in the masked values. 

5754 If None, use the output of `minimum_fill_value`. 

5755 keepdims : bool, optional 

5756 If this is set to True, the axes which are reduced are left 

5757 in the result as dimensions with size one. With this option, 

5758 the result will broadcast correctly against the array. 

5759 

5760 Returns 

5761 ------- 

5762 amin : array_like 

5763 New array holding the result. 

5764 If ``out`` was specified, ``out`` is returned. 

5765 

5766 See Also 

5767 -------- 

5768 ma.minimum_fill_value 

5769 Returns the minimum filling value for a given datatype. 

5770 

5771 Examples 

5772 -------- 

5773 >>> import numpy.ma as ma 

5774 >>> x = [[1., -2., 3.], [0.2, -0.7, 0.1]] 

5775 >>> mask = [[1, 1, 0], [0, 0, 1]] 

5776 >>> masked_x = ma.masked_array(x, mask) 

5777 >>> masked_x 

5778 masked_array( 

5779 data=[[--, --, 3.0], 

5780 [0.2, -0.7, --]], 

5781 mask=[[ True, True, False], 

5782 [False, False, True]], 

5783 fill_value=1e+20) 

5784 >>> ma.min(masked_x) 

5785 -0.7 

5786 >>> ma.min(masked_x, axis=-1) 

5787 masked_array(data=[3.0, -0.7], 

5788 mask=[False, False], 

5789 fill_value=1e+20) 

5790 >>> ma.min(masked_x, axis=0, keepdims=True) 

5791 masked_array(data=[[0.2, -0.7, 3.0]], 

5792 mask=[[False, False, False]], 

5793 fill_value=1e+20) 

5794 >>> mask = [[1, 1, 1,], [1, 1, 1]] 

5795 >>> masked_x = ma.masked_array(x, mask) 

5796 >>> ma.min(masked_x, axis=0) 

5797 masked_array(data=[--, --, --], 

5798 mask=[ True, True, True], 

5799 fill_value=1e+20, 

5800 dtype=float64) 

5801 """ 

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

5803 

5804 _mask = self._mask 

5805 newmask = _check_mask_axis(_mask, axis, **kwargs) 

5806 if fill_value is None: 

5807 fill_value = minimum_fill_value(self) 

5808 # No explicit output 

5809 if out is None: 

5810 result = self.filled(fill_value).min( 

5811 axis=axis, out=out, **kwargs).view(type(self)) 

5812 if result.ndim: 

5813 # Set the mask 

5814 result.__setmask__(newmask) 

5815 # Get rid of Infs 

5816 if newmask.ndim: 

5817 np.copyto(result, result.fill_value, where=newmask) 

5818 elif newmask: 

5819 result = masked 

5820 return result 

5821 # Explicit output 

5822 result = self.filled(fill_value).min(axis=axis, out=out, **kwargs) 

5823 if isinstance(out, MaskedArray): 

5824 outmask = getmask(out) 

5825 if outmask is nomask: 

5826 outmask = out._mask = make_mask_none(out.shape) 

5827 outmask.flat = newmask 

5828 else: 

5829 if out.dtype.kind in 'biu': 

5830 errmsg = "Masked data information would be lost in one or more"\ 

5831 " location." 

5832 raise MaskError(errmsg) 

5833 np.copyto(out, np.nan, where=newmask) 

5834 return out 

5835 

5836 def max(self, axis=None, out=None, fill_value=None, keepdims=np._NoValue): 

5837 """ 

5838 Return the maximum along a given axis. 

5839 

5840 Parameters 

5841 ---------- 

5842 axis : None or int or tuple of ints, optional 

5843 Axis along which to operate. By default, ``axis`` is None and the 

5844 flattened input is used. 

5845 .. versionadded:: 1.7.0 

5846 If this is a tuple of ints, the maximum is selected over multiple 

5847 axes, instead of a single axis or all the axes as before. 

5848 out : array_like, optional 

5849 Alternative output array in which to place the result. Must 

5850 be of the same shape and buffer length as the expected output. 

5851 fill_value : scalar or None, optional 

5852 Value used to fill in the masked values. 

5853 If None, use the output of maximum_fill_value(). 

5854 keepdims : bool, optional 

5855 If this is set to True, the axes which are reduced are left 

5856 in the result as dimensions with size one. With this option, 

5857 the result will broadcast correctly against the array. 

5858 

5859 Returns 

5860 ------- 

5861 amax : array_like 

5862 New array holding the result. 

5863 If ``out`` was specified, ``out`` is returned. 

5864 

5865 See Also 

5866 -------- 

5867 ma.maximum_fill_value 

5868 Returns the maximum filling value for a given datatype. 

5869 

5870 Examples 

5871 -------- 

5872 >>> import numpy.ma as ma 

5873 >>> x = [[-1., 2.5], [4., -2.], [3., 0.]] 

5874 >>> mask = [[0, 0], [1, 0], [1, 0]] 

5875 >>> masked_x = ma.masked_array(x, mask) 

5876 >>> masked_x 

5877 masked_array( 

5878 data=[[-1.0, 2.5], 

5879 [--, -2.0], 

5880 [--, 0.0]], 

5881 mask=[[False, False], 

5882 [ True, False], 

5883 [ True, False]], 

5884 fill_value=1e+20) 

5885 >>> ma.max(masked_x) 

5886 2.5 

5887 >>> ma.max(masked_x, axis=0) 

5888 masked_array(data=[-1.0, 2.5], 

5889 mask=[False, False], 

5890 fill_value=1e+20) 

5891 >>> ma.max(masked_x, axis=1, keepdims=True) 

5892 masked_array( 

5893 data=[[2.5], 

5894 [-2.0], 

5895 [0.0]], 

5896 mask=[[False], 

5897 [False], 

5898 [False]], 

5899 fill_value=1e+20) 

5900 >>> mask = [[1, 1], [1, 1], [1, 1]] 

5901 >>> masked_x = ma.masked_array(x, mask) 

5902 >>> ma.max(masked_x, axis=1) 

5903 masked_array(data=[--, --, --], 

5904 mask=[ True, True, True], 

5905 fill_value=1e+20, 

5906 dtype=float64) 

5907 """ 

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

5909 

5910 _mask = self._mask 

5911 newmask = _check_mask_axis(_mask, axis, **kwargs) 

5912 if fill_value is None: 

5913 fill_value = maximum_fill_value(self) 

5914 # No explicit output 

5915 if out is None: 

5916 result = self.filled(fill_value).max( 

5917 axis=axis, out=out, **kwargs).view(type(self)) 

5918 if result.ndim: 

5919 # Set the mask 

5920 result.__setmask__(newmask) 

5921 # Get rid of Infs 

5922 if newmask.ndim: 

5923 np.copyto(result, result.fill_value, where=newmask) 

5924 elif newmask: 

5925 result = masked 

5926 return result 

5927 # Explicit output 

5928 result = self.filled(fill_value).max(axis=axis, out=out, **kwargs) 

5929 if isinstance(out, MaskedArray): 

5930 outmask = getmask(out) 

5931 if outmask is nomask: 

5932 outmask = out._mask = make_mask_none(out.shape) 

5933 outmask.flat = newmask 

5934 else: 

5935 

5936 if out.dtype.kind in 'biu': 

5937 errmsg = "Masked data information would be lost in one or more"\ 

5938 " location." 

5939 raise MaskError(errmsg) 

5940 np.copyto(out, np.nan, where=newmask) 

5941 return out 

5942 

5943 def ptp(self, axis=None, out=None, fill_value=None, keepdims=False): 

5944 """ 

5945 Return (maximum - minimum) along the given dimension 

5946 (i.e. peak-to-peak value). 

5947 

5948 .. warning:: 

5949 `ptp` preserves the data type of the array. This means the 

5950 return value for an input of signed integers with n bits 

5951 (e.g. `np.int8`, `np.int16`, etc) is also a signed integer 

5952 with n bits. In that case, peak-to-peak values greater than 

5953 ``2**(n-1)-1`` will be returned as negative values. An example 

5954 with a work-around is shown below. 

5955 

5956 Parameters 

5957 ---------- 

5958 axis : {None, int}, optional 

5959 Axis along which to find the peaks. If None (default) the 

5960 flattened array is used. 

5961 out : {None, array_like}, optional 

5962 Alternative output array in which to place the result. It must 

5963 have the same shape and buffer length as the expected output 

5964 but the type will be cast if necessary. 

5965 fill_value : scalar or None, optional 

5966 Value used to fill in the masked values. 

5967 keepdims : bool, optional 

5968 If this is set to True, the axes which are reduced are left 

5969 in the result as dimensions with size one. With this option, 

5970 the result will broadcast correctly against the array. 

5971 

5972 Returns 

5973 ------- 

5974 ptp : ndarray. 

5975 A new array holding the result, unless ``out`` was 

5976 specified, in which case a reference to ``out`` is returned. 

5977 

5978 Examples 

5979 -------- 

5980 >>> x = np.ma.MaskedArray([[4, 9, 2, 10], 

5981 ... [6, 9, 7, 12]]) 

5982 

5983 >>> x.ptp(axis=1) 

5984 masked_array(data=[8, 6], 

5985 mask=False, 

5986 fill_value=999999) 

5987 

5988 >>> x.ptp(axis=0) 

5989 masked_array(data=[2, 0, 5, 2], 

5990 mask=False, 

5991 fill_value=999999) 

5992 

5993 >>> x.ptp() 

5994 10 

5995 

5996 This example shows that a negative value can be returned when 

5997 the input is an array of signed integers. 

5998 

5999 >>> y = np.ma.MaskedArray([[1, 127], 

6000 ... [0, 127], 

6001 ... [-1, 127], 

6002 ... [-2, 127]], dtype=np.int8) 

6003 >>> y.ptp(axis=1) 

6004 masked_array(data=[ 126, 127, -128, -127], 

6005 mask=False, 

6006 fill_value=999999, 

6007 dtype=int8) 

6008 

6009 A work-around is to use the `view()` method to view the result as 

6010 unsigned integers with the same bit width: 

6011 

6012 >>> y.ptp(axis=1).view(np.uint8) 

6013 masked_array(data=[126, 127, 128, 129], 

6014 mask=False, 

6015 fill_value=999999, 

6016 dtype=uint8) 

6017 """ 

6018 if out is None: 

6019 result = self.max(axis=axis, fill_value=fill_value, 

6020 keepdims=keepdims) 

6021 result -= self.min(axis=axis, fill_value=fill_value, 

6022 keepdims=keepdims) 

6023 return result 

6024 out.flat = self.max(axis=axis, out=out, fill_value=fill_value, 

6025 keepdims=keepdims) 

6026 min_value = self.min(axis=axis, fill_value=fill_value, 

6027 keepdims=keepdims) 

6028 np.subtract(out, min_value, out=out, casting='unsafe') 

6029 return out 

6030 

6031 def partition(self, *args, **kwargs): 

6032 warnings.warn("Warning: 'partition' will ignore the 'mask' " 

6033 f"of the {self.__class__.__name__}.", 

6034 stacklevel=2) 

6035 return super().partition(*args, **kwargs) 

6036 

6037 def argpartition(self, *args, **kwargs): 

6038 warnings.warn("Warning: 'argpartition' will ignore the 'mask' " 

6039 f"of the {self.__class__.__name__}.", 

6040 stacklevel=2) 

6041 return super().argpartition(*args, **kwargs) 

6042 

6043 def take(self, indices, axis=None, out=None, mode='raise'): 

6044 """ 

6045 """ 

6046 (_data, _mask) = (self._data, self._mask) 

6047 cls = type(self) 

6048 # Make sure the indices are not masked 

6049 maskindices = getmask(indices) 

6050 if maskindices is not nomask: 

6051 indices = indices.filled(0) 

6052 # Get the data, promoting scalars to 0d arrays with [...] so that 

6053 # .view works correctly 

6054 if out is None: 

6055 out = _data.take(indices, axis=axis, mode=mode)[...].view(cls) 

6056 else: 

6057 np.take(_data, indices, axis=axis, mode=mode, out=out) 

6058 # Get the mask 

6059 if isinstance(out, MaskedArray): 

6060 if _mask is nomask: 

6061 outmask = maskindices 

6062 else: 

6063 outmask = _mask.take(indices, axis=axis, mode=mode) 

6064 outmask |= maskindices 

6065 out.__setmask__(outmask) 

6066 # demote 0d arrays back to scalars, for consistency with ndarray.take 

6067 return out[()] 

6068 

6069 # Array methods 

6070 copy = _arraymethod('copy') 

6071 diagonal = _arraymethod('diagonal') 

6072 flatten = _arraymethod('flatten') 

6073 repeat = _arraymethod('repeat') 

6074 squeeze = _arraymethod('squeeze') 

6075 swapaxes = _arraymethod('swapaxes') 

6076 T = property(fget=lambda self: self.transpose()) 

6077 transpose = _arraymethod('transpose') 

6078 

6079 def tolist(self, fill_value=None): 

6080 """ 

6081 Return the data portion of the masked array as a hierarchical Python list. 

6082 

6083 Data items are converted to the nearest compatible Python type. 

6084 Masked values are converted to `fill_value`. If `fill_value` is None, 

6085 the corresponding entries in the output list will be ``None``. 

6086 

6087 Parameters 

6088 ---------- 

6089 fill_value : scalar, optional 

6090 The value to use for invalid entries. Default is None. 

6091 

6092 Returns 

6093 ------- 

6094 result : list 

6095 The Python list representation of the masked array. 

6096 

6097 Examples 

6098 -------- 

6099 >>> x = np.ma.array([[1,2,3], [4,5,6], [7,8,9]], mask=[0] + [1,0]*4) 

6100 >>> x.tolist() 

6101 [[1, None, 3], [None, 5, None], [7, None, 9]] 

6102 >>> x.tolist(-999) 

6103 [[1, -999, 3], [-999, 5, -999], [7, -999, 9]] 

6104 

6105 """ 

6106 _mask = self._mask 

6107 # No mask ? Just return .data.tolist ? 

6108 if _mask is nomask: 

6109 return self._data.tolist() 

6110 # Explicit fill_value: fill the array and get the list 

6111 if fill_value is not None: 

6112 return self.filled(fill_value).tolist() 

6113 # Structured array. 

6114 names = self.dtype.names 

6115 if names: 

6116 result = self._data.astype([(_, object) for _ in names]) 

6117 for n in names: 

6118 result[n][_mask[n]] = None 

6119 return result.tolist() 

6120 # Standard arrays. 

6121 if _mask is nomask: 

6122 return [None] 

6123 # Set temps to save time when dealing w/ marrays. 

6124 inishape = self.shape 

6125 result = np.array(self._data.ravel(), dtype=object) 

6126 result[_mask.ravel()] = None 

6127 result.shape = inishape 

6128 return result.tolist() 

6129 

6130 def tostring(self, fill_value=None, order='C'): 

6131 r""" 

6132 A compatibility alias for `tobytes`, with exactly the same behavior. 

6133 

6134 Despite its name, it returns `bytes` not `str`\ s. 

6135 

6136 .. deprecated:: 1.19.0 

6137 """ 

6138 # 2020-03-30, Numpy 1.19.0 

6139 warnings.warn( 

6140 "tostring() is deprecated. Use tobytes() instead.", 

6141 DeprecationWarning, stacklevel=2) 

6142 

6143 return self.tobytes(fill_value, order=order) 

6144 

6145 def tobytes(self, fill_value=None, order='C'): 

6146 """ 

6147 Return the array data as a string containing the raw bytes in the array. 

6148 

6149 The array is filled with a fill value before the string conversion. 

6150 

6151 .. versionadded:: 1.9.0 

6152 

6153 Parameters 

6154 ---------- 

6155 fill_value : scalar, optional 

6156 Value used to fill in the masked values. Default is None, in which 

6157 case `MaskedArray.fill_value` is used. 

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

6159 Order of the data item in the copy. Default is 'C'. 

6160 

6161 - 'C' -- C order (row major). 

6162 - 'F' -- Fortran order (column major). 

6163 - 'A' -- Any, current order of array. 

6164 - None -- Same as 'A'. 

6165 

6166 See Also 

6167 -------- 

6168 numpy.ndarray.tobytes 

6169 tolist, tofile 

6170 

6171 Notes 

6172 ----- 

6173 As for `ndarray.tobytes`, information about the shape, dtype, etc., 

6174 but also about `fill_value`, will be lost. 

6175 

6176 Examples 

6177 -------- 

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

6179 >>> x.tobytes() 

6180 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' 

6181 

6182 """ 

6183 return self.filled(fill_value).tobytes(order=order) 

6184 

6185 def tofile(self, fid, sep="", format="%s"): 

6186 """ 

6187 Save a masked array to a file in binary format. 

6188 

6189 .. warning:: 

6190 This function is not implemented yet. 

6191 

6192 Raises 

6193 ------ 

6194 NotImplementedError 

6195 When `tofile` is called. 

6196 

6197 """ 

6198 raise NotImplementedError("MaskedArray.tofile() not implemented yet.") 

6199 

6200 def toflex(self): 

6201 """ 

6202 Transforms a masked array into a flexible-type array. 

6203 

6204 The flexible type array that is returned will have two fields: 

6205 

6206 * the ``_data`` field stores the ``_data`` part of the array. 

6207 * the ``_mask`` field stores the ``_mask`` part of the array. 

6208 

6209 Parameters 

6210 ---------- 

6211 None 

6212 

6213 Returns 

6214 ------- 

6215 record : ndarray 

6216 A new flexible-type `ndarray` with two fields: the first element 

6217 containing a value, the second element containing the corresponding 

6218 mask boolean. The returned record shape matches self.shape. 

6219 

6220 Notes 

6221 ----- 

6222 A side-effect of transforming a masked array into a flexible `ndarray` is 

6223 that meta information (``fill_value``, ...) will be lost. 

6224 

6225 Examples 

6226 -------- 

6227 >>> x = np.ma.array([[1,2,3],[4,5,6],[7,8,9]], mask=[0] + [1,0]*4) 

6228 >>> x 

6229 masked_array( 

6230 data=[[1, --, 3], 

6231 [--, 5, --], 

6232 [7, --, 9]], 

6233 mask=[[False, True, False], 

6234 [ True, False, True], 

6235 [False, True, False]], 

6236 fill_value=999999) 

6237 >>> x.toflex() 

6238 array([[(1, False), (2, True), (3, False)], 

6239 [(4, True), (5, False), (6, True)], 

6240 [(7, False), (8, True), (9, False)]], 

6241 dtype=[('_data', '<i8'), ('_mask', '?')]) 

6242 

6243 """ 

6244 # Get the basic dtype. 

6245 ddtype = self.dtype 

6246 # Make sure we have a mask 

6247 _mask = self._mask 

6248 if _mask is None: 

6249 _mask = make_mask_none(self.shape, ddtype) 

6250 # And get its dtype 

6251 mdtype = self._mask.dtype 

6252 

6253 record = np.ndarray(shape=self.shape, 

6254 dtype=[('_data', ddtype), ('_mask', mdtype)]) 

6255 record['_data'] = self._data 

6256 record['_mask'] = self._mask 

6257 return record 

6258 torecords = toflex 

6259 

6260 # Pickling 

6261 def __getstate__(self): 

6262 """Return the internal state of the masked array, for pickling 

6263 purposes. 

6264 

6265 """ 

6266 cf = 'CF'[self.flags.fnc] 

6267 data_state = super().__reduce__()[2] 

6268 return data_state + (getmaskarray(self).tobytes(cf), self._fill_value) 

6269 

6270 def __setstate__(self, state): 

6271 """Restore the internal state of the masked array, for 

6272 pickling purposes. ``state`` is typically the output of the 

6273 ``__getstate__`` output, and is a 5-tuple: 

6274 

6275 - class name 

6276 - a tuple giving the shape of the data 

6277 - a typecode for the data 

6278 - a binary string for the data 

6279 - a binary string for the mask. 

6280 

6281 """ 

6282 (_, shp, typ, isf, raw, msk, flv) = state 

6283 super().__setstate__((shp, typ, isf, raw)) 

6284 self._mask.__setstate__((shp, make_mask_descr(typ), isf, msk)) 

6285 self.fill_value = flv 

6286 

6287 def __reduce__(self): 

6288 """Return a 3-tuple for pickling a MaskedArray. 

6289 

6290 """ 

6291 return (_mareconstruct, 

6292 (self.__class__, self._baseclass, (0,), 'b',), 

6293 self.__getstate__()) 

6294 

6295 def __deepcopy__(self, memo=None): 

6296 from copy import deepcopy 

6297 copied = MaskedArray.__new__(type(self), self, copy=True) 

6298 if memo is None: 

6299 memo = {} 

6300 memo[id(self)] = copied 

6301 for (k, v) in self.__dict__.items(): 

6302 copied.__dict__[k] = deepcopy(v, memo) 

6303 return copied 

6304 

6305 

6306def _mareconstruct(subtype, baseclass, baseshape, basetype,): 

6307 """Internal function that builds a new MaskedArray from the 

6308 information stored in a pickle. 

6309 

6310 """ 

6311 _data = ndarray.__new__(baseclass, baseshape, basetype) 

6312 _mask = ndarray.__new__(ndarray, baseshape, make_mask_descr(basetype)) 

6313 return subtype.__new__(subtype, _data, mask=_mask, dtype=basetype,) 

6314 

6315 

6316class mvoid(MaskedArray): 

6317 """ 

6318 Fake a 'void' object to use for masked array with structured dtypes. 

6319 """ 

6320 

6321 def __new__(self, data, mask=nomask, dtype=None, fill_value=None, 

6322 hardmask=False, copy=False, subok=True): 

6323 _data = np.array(data, copy=copy, subok=subok, dtype=dtype) 

6324 _data = _data.view(self) 

6325 _data._hardmask = hardmask 

6326 if mask is not nomask: 

6327 if isinstance(mask, np.void): 

6328 _data._mask = mask 

6329 else: 

6330 try: 

6331 # Mask is already a 0D array 

6332 _data._mask = np.void(mask) 

6333 except TypeError: 

6334 # Transform the mask to a void 

6335 mdtype = make_mask_descr(dtype) 

6336 _data._mask = np.array(mask, dtype=mdtype)[()] 

6337 if fill_value is not None: 

6338 _data.fill_value = fill_value 

6339 return _data 

6340 

6341 @property 

6342 def _data(self): 

6343 # Make sure that the _data part is a np.void 

6344 return super()._data[()] 

6345 

6346 def __getitem__(self, indx): 

6347 """ 

6348 Get the index. 

6349 

6350 """ 

6351 m = self._mask 

6352 if isinstance(m[indx], ndarray): 

6353 # Can happen when indx is a multi-dimensional field: 

6354 # A = ma.masked_array(data=[([0,1],)], mask=[([True, 

6355 # False],)], dtype=[("A", ">i2", (2,))]) 

6356 # x = A[0]; y = x["A"]; then y.mask["A"].size==2 

6357 # and we can not say masked/unmasked. 

6358 # The result is no longer mvoid! 

6359 # See also issue #6724. 

6360 return masked_array( 

6361 data=self._data[indx], mask=m[indx], 

6362 fill_value=self._fill_value[indx], 

6363 hard_mask=self._hardmask) 

6364 if m is not nomask and m[indx]: 

6365 return masked 

6366 return self._data[indx] 

6367 

6368 def __setitem__(self, indx, value): 

6369 self._data[indx] = value 

6370 if self._hardmask: 

6371 self._mask[indx] |= getattr(value, "_mask", False) 

6372 else: 

6373 self._mask[indx] = getattr(value, "_mask", False) 

6374 

6375 def __str__(self): 

6376 m = self._mask 

6377 if m is nomask: 

6378 return str(self._data) 

6379 

6380 rdtype = _replace_dtype_fields(self._data.dtype, "O") 

6381 data_arr = super()._data 

6382 res = data_arr.astype(rdtype) 

6383 _recursive_printoption(res, self._mask, masked_print_option) 

6384 return str(res) 

6385 

6386 __repr__ = __str__ 

6387 

6388 def __iter__(self): 

6389 "Defines an iterator for mvoid" 

6390 (_data, _mask) = (self._data, self._mask) 

6391 if _mask is nomask: 

6392 yield from _data 

6393 else: 

6394 for (d, m) in zip(_data, _mask): 

6395 if m: 

6396 yield masked 

6397 else: 

6398 yield d 

6399 

6400 def __len__(self): 

6401 return self._data.__len__() 

6402 

6403 def filled(self, fill_value=None): 

6404 """ 

6405 Return a copy with masked fields filled with a given value. 

6406 

6407 Parameters 

6408 ---------- 

6409 fill_value : array_like, optional 

6410 The value to use for invalid entries. Can be scalar or 

6411 non-scalar. If latter is the case, the filled array should 

6412 be broadcastable over input array. Default is None, in 

6413 which case the `fill_value` attribute is used instead. 

6414 

6415 Returns 

6416 ------- 

6417 filled_void 

6418 A `np.void` object 

6419 

6420 See Also 

6421 -------- 

6422 MaskedArray.filled 

6423 

6424 """ 

6425 return asarray(self).filled(fill_value)[()] 

6426 

6427 def tolist(self): 

6428 """ 

6429 Transforms the mvoid object into a tuple. 

6430 

6431 Masked fields are replaced by None. 

6432 

6433 Returns 

6434 ------- 

6435 returned_tuple 

6436 Tuple of fields 

6437 """ 

6438 _mask = self._mask 

6439 if _mask is nomask: 

6440 return self._data.tolist() 

6441 result = [] 

6442 for (d, m) in zip(self._data, self._mask): 

6443 if m: 

6444 result.append(None) 

6445 else: 

6446 # .item() makes sure we return a standard Python object 

6447 result.append(d.item()) 

6448 return tuple(result) 

6449 

6450 

6451############################################################################## 

6452# Shortcuts # 

6453############################################################################## 

6454 

6455 

6456def isMaskedArray(x): 

6457 """ 

6458 Test whether input is an instance of MaskedArray. 

6459 

6460 This function returns True if `x` is an instance of MaskedArray 

6461 and returns False otherwise. Any object is accepted as input. 

6462 

6463 Parameters 

6464 ---------- 

6465 x : object 

6466 Object to test. 

6467 

6468 Returns 

6469 ------- 

6470 result : bool 

6471 True if `x` is a MaskedArray. 

6472 

6473 See Also 

6474 -------- 

6475 isMA : Alias to isMaskedArray. 

6476 isarray : Alias to isMaskedArray. 

6477 

6478 Examples 

6479 -------- 

6480 >>> import numpy.ma as ma 

6481 >>> a = np.eye(3, 3) 

6482 >>> a 

6483 array([[ 1., 0., 0.], 

6484 [ 0., 1., 0.], 

6485 [ 0., 0., 1.]]) 

6486 >>> m = ma.masked_values(a, 0) 

6487 >>> m 

6488 masked_array( 

6489 data=[[1.0, --, --], 

6490 [--, 1.0, --], 

6491 [--, --, 1.0]], 

6492 mask=[[False, True, True], 

6493 [ True, False, True], 

6494 [ True, True, False]], 

6495 fill_value=0.0) 

6496 >>> ma.isMaskedArray(a) 

6497 False 

6498 >>> ma.isMaskedArray(m) 

6499 True 

6500 >>> ma.isMaskedArray([0, 1, 2]) 

6501 False 

6502 

6503 """ 

6504 return isinstance(x, MaskedArray) 

6505 

6506 

6507isarray = isMaskedArray 

6508isMA = isMaskedArray # backward compatibility 

6509 

6510 

6511class MaskedConstant(MaskedArray): 

6512 # the lone np.ma.masked instance 

6513 __singleton = None 

6514 

6515 @classmethod 

6516 def __has_singleton(cls): 

6517 # second case ensures `cls.__singleton` is not just a view on the 

6518 # superclass singleton 

6519 return cls.__singleton is not None and type(cls.__singleton) is cls 

6520 

6521 def __new__(cls): 

6522 if not cls.__has_singleton(): 

6523 # We define the masked singleton as a float for higher precedence. 

6524 # Note that it can be tricky sometimes w/ type comparison 

6525 data = np.array(0.) 

6526 mask = np.array(True) 

6527 

6528 # prevent any modifications 

6529 data.flags.writeable = False 

6530 mask.flags.writeable = False 

6531 

6532 # don't fall back on MaskedArray.__new__(MaskedConstant), since 

6533 # that might confuse it - this way, the construction is entirely 

6534 # within our control 

6535 cls.__singleton = MaskedArray(data, mask=mask).view(cls) 

6536 

6537 return cls.__singleton 

6538 

6539 def __array_finalize__(self, obj): 

6540 if not self.__has_singleton(): 

6541 # this handles the `.view` in __new__, which we want to copy across 

6542 # properties normally 

6543 return super().__array_finalize__(obj) 

6544 elif self is self.__singleton: 

6545 # not clear how this can happen, play it safe 

6546 pass 

6547 else: 

6548 # everywhere else, we want to downcast to MaskedArray, to prevent a 

6549 # duplicate maskedconstant. 

6550 self.__class__ = MaskedArray 

6551 MaskedArray.__array_finalize__(self, obj) 

6552 

6553 def __array_prepare__(self, obj, context=None): 

6554 return self.view(MaskedArray).__array_prepare__(obj, context) 

6555 

6556 def __array_wrap__(self, obj, context=None): 

6557 return self.view(MaskedArray).__array_wrap__(obj, context) 

6558 

6559 def __str__(self): 

6560 return str(masked_print_option._display) 

6561 

6562 def __repr__(self): 

6563 if self is MaskedConstant.__singleton: 

6564 return 'masked' 

6565 else: 

6566 # it's a subclass, or something is wrong, make it obvious 

6567 return object.__repr__(self) 

6568 

6569 def __format__(self, format_spec): 

6570 # Replace ndarray.__format__ with the default, which supports no format characters. 

6571 # Supporting format characters is unwise here, because we do not know what type 

6572 # the user was expecting - better to not guess. 

6573 try: 

6574 return object.__format__(self, format_spec) 

6575 except TypeError: 

6576 # 2020-03-23, NumPy 1.19.0 

6577 warnings.warn( 

6578 "Format strings passed to MaskedConstant are ignored, but in future may " 

6579 "error or produce different behavior", 

6580 FutureWarning, stacklevel=2 

6581 ) 

6582 return object.__format__(self, "") 

6583 

6584 def __reduce__(self): 

6585 """Override of MaskedArray's __reduce__. 

6586 """ 

6587 return (self.__class__, ()) 

6588 

6589 # inplace operations have no effect. We have to override them to avoid 

6590 # trying to modify the readonly data and mask arrays 

6591 def __iop__(self, other): 

6592 return self 

6593 __iadd__ = \ 

6594 __isub__ = \ 

6595 __imul__ = \ 

6596 __ifloordiv__ = \ 

6597 __itruediv__ = \ 

6598 __ipow__ = \ 

6599 __iop__ 

6600 del __iop__ # don't leave this around 

6601 

6602 def copy(self, *args, **kwargs): 

6603 """ Copy is a no-op on the maskedconstant, as it is a scalar """ 

6604 # maskedconstant is a scalar, so copy doesn't need to copy. There's 

6605 # precedent for this with `np.bool_` scalars. 

6606 return self 

6607 

6608 def __copy__(self): 

6609 return self 

6610 

6611 def __deepcopy__(self, memo): 

6612 return self 

6613 

6614 def __setattr__(self, attr, value): 

6615 if not self.__has_singleton(): 

6616 # allow the singleton to be initialized 

6617 return super().__setattr__(attr, value) 

6618 elif self is self.__singleton: 

6619 raise AttributeError( 

6620 f"attributes of {self!r} are not writeable") 

6621 else: 

6622 # duplicate instance - we can end up here from __array_finalize__, 

6623 # where we set the __class__ attribute 

6624 return super().__setattr__(attr, value) 

6625 

6626 

6627masked = masked_singleton = MaskedConstant() 

6628masked_array = MaskedArray 

6629 

6630 

6631def array(data, dtype=None, copy=False, order=None, 

6632 mask=nomask, fill_value=None, keep_mask=True, 

6633 hard_mask=False, shrink=True, subok=True, ndmin=0): 

6634 """ 

6635 Shortcut to MaskedArray. 

6636 

6637 The options are in a different order for convenience and backwards 

6638 compatibility. 

6639 

6640 """ 

6641 return MaskedArray(data, mask=mask, dtype=dtype, copy=copy, 

6642 subok=subok, keep_mask=keep_mask, 

6643 hard_mask=hard_mask, fill_value=fill_value, 

6644 ndmin=ndmin, shrink=shrink, order=order) 

6645array.__doc__ = masked_array.__doc__ 

6646 

6647 

6648def is_masked(x): 

6649 """ 

6650 Determine whether input has masked values. 

6651 

6652 Accepts any object as input, but always returns False unless the 

6653 input is a MaskedArray containing masked values. 

6654 

6655 Parameters 

6656 ---------- 

6657 x : array_like 

6658 Array to check for masked values. 

6659 

6660 Returns 

6661 ------- 

6662 result : bool 

6663 True if `x` is a MaskedArray with masked values, False otherwise. 

6664 

6665 Examples 

6666 -------- 

6667 >>> import numpy.ma as ma 

6668 >>> x = ma.masked_equal([0, 1, 0, 2, 3], 0) 

6669 >>> x 

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

6671 mask=[ True, False, True, False, False], 

6672 fill_value=0) 

6673 >>> ma.is_masked(x) 

6674 True 

6675 >>> x = ma.masked_equal([0, 1, 0, 2, 3], 42) 

6676 >>> x 

6677 masked_array(data=[0, 1, 0, 2, 3], 

6678 mask=False, 

6679 fill_value=42) 

6680 >>> ma.is_masked(x) 

6681 False 

6682 

6683 Always returns False if `x` isn't a MaskedArray. 

6684 

6685 >>> x = [False, True, False] 

6686 >>> ma.is_masked(x) 

6687 False 

6688 >>> x = 'a string' 

6689 >>> ma.is_masked(x) 

6690 False 

6691 

6692 """ 

6693 m = getmask(x) 

6694 if m is nomask: 

6695 return False 

6696 elif m.any(): 

6697 return True 

6698 return False 

6699 

6700 

6701############################################################################## 

6702# Extrema functions # 

6703############################################################################## 

6704 

6705 

6706class _extrema_operation(_MaskedUFunc): 

6707 """ 

6708 Generic class for maximum/minimum functions. 

6709 

6710 .. note:: 

6711 This is the base class for `_maximum_operation` and 

6712 `_minimum_operation`. 

6713 

6714 """ 

6715 def __init__(self, ufunc, compare, fill_value): 

6716 super().__init__(ufunc) 

6717 self.compare = compare 

6718 self.fill_value_func = fill_value 

6719 

6720 def __call__(self, a, b): 

6721 "Executes the call behavior." 

6722 

6723 return where(self.compare(a, b), a, b) 

6724 

6725 def reduce(self, target, axis=np._NoValue): 

6726 "Reduce target along the given axis." 

6727 target = narray(target, copy=False, subok=True) 

6728 m = getmask(target) 

6729 

6730 if axis is np._NoValue and target.ndim > 1: 

6731 # 2017-05-06, Numpy 1.13.0: warn on axis default 

6732 warnings.warn( 

6733 f"In the future the default for ma.{self.__name__}.reduce will be axis=0, " 

6734 f"not the current None, to match np.{self.__name__}.reduce. " 

6735 "Explicitly pass 0 or None to silence this warning.", 

6736 MaskedArrayFutureWarning, stacklevel=2) 

6737 axis = None 

6738 

6739 if axis is not np._NoValue: 

6740 kwargs = dict(axis=axis) 

6741 else: 

6742 kwargs = dict() 

6743 

6744 if m is nomask: 

6745 t = self.f.reduce(target, **kwargs) 

6746 else: 

6747 target = target.filled( 

6748 self.fill_value_func(target)).view(type(target)) 

6749 t = self.f.reduce(target, **kwargs) 

6750 m = umath.logical_and.reduce(m, **kwargs) 

6751 if hasattr(t, '_mask'): 

6752 t._mask = m 

6753 elif m: 

6754 t = masked 

6755 return t 

6756 

6757 def outer(self, a, b): 

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

6759 ma = getmask(a) 

6760 mb = getmask(b) 

6761 if ma is nomask and mb is nomask: 

6762 m = nomask 

6763 else: 

6764 ma = getmaskarray(a) 

6765 mb = getmaskarray(b) 

6766 m = logical_or.outer(ma, mb) 

6767 result = self.f.outer(filled(a), filled(b)) 

6768 if not isinstance(result, MaskedArray): 

6769 result = result.view(MaskedArray) 

6770 result._mask = m 

6771 return result 

6772 

6773def min(obj, axis=None, out=None, fill_value=None, keepdims=np._NoValue): 

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

6775 

6776 try: 

6777 return obj.min(axis=axis, fill_value=fill_value, out=out, **kwargs) 

6778 except (AttributeError, TypeError): 

6779 # If obj doesn't have a min method, or if the method doesn't accept a 

6780 # fill_value argument 

6781 return asanyarray(obj).min(axis=axis, fill_value=fill_value, 

6782 out=out, **kwargs) 

6783min.__doc__ = MaskedArray.min.__doc__ 

6784 

6785def max(obj, axis=None, out=None, fill_value=None, keepdims=np._NoValue): 

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

6787 

6788 try: 

6789 return obj.max(axis=axis, fill_value=fill_value, out=out, **kwargs) 

6790 except (AttributeError, TypeError): 

6791 # If obj doesn't have a max method, or if the method doesn't accept a 

6792 # fill_value argument 

6793 return asanyarray(obj).max(axis=axis, fill_value=fill_value, 

6794 out=out, **kwargs) 

6795max.__doc__ = MaskedArray.max.__doc__ 

6796 

6797 

6798def ptp(obj, axis=None, out=None, fill_value=None, keepdims=np._NoValue): 

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

6800 try: 

6801 return obj.ptp(axis, out=out, fill_value=fill_value, **kwargs) 

6802 except (AttributeError, TypeError): 

6803 # If obj doesn't have a ptp method or if the method doesn't accept 

6804 # a fill_value argument 

6805 return asanyarray(obj).ptp(axis=axis, fill_value=fill_value, 

6806 out=out, **kwargs) 

6807ptp.__doc__ = MaskedArray.ptp.__doc__ 

6808 

6809 

6810############################################################################## 

6811# Definition of functions from the corresponding methods # 

6812############################################################################## 

6813 

6814 

6815class _frommethod: 

6816 """ 

6817 Define functions from existing MaskedArray methods. 

6818 

6819 Parameters 

6820 ---------- 

6821 methodname : str 

6822 Name of the method to transform. 

6823 

6824 """ 

6825 

6826 def __init__(self, methodname, reversed=False): 

6827 self.__name__ = methodname 

6828 self.__doc__ = self.getdoc() 

6829 self.reversed = reversed 

6830 

6831 def getdoc(self): 

6832 "Return the doc of the function (from the doc of the method)." 

6833 meth = getattr(MaskedArray, self.__name__, None) or\ 

6834 getattr(np, self.__name__, None) 

6835 signature = self.__name__ + get_object_signature(meth) 

6836 if meth is not None: 

6837 doc = """ %s\n%s""" % ( 

6838 signature, getattr(meth, '__doc__', None)) 

6839 return doc 

6840 

6841 def __call__(self, a, *args, **params): 

6842 if self.reversed: 

6843 args = list(args) 

6844 a, args[0] = args[0], a 

6845 

6846 marr = asanyarray(a) 

6847 method_name = self.__name__ 

6848 method = getattr(type(marr), method_name, None) 

6849 if method is None: 

6850 # use the corresponding np function 

6851 method = getattr(np, method_name) 

6852 

6853 return method(marr, *args, **params) 

6854 

6855 

6856all = _frommethod('all') 

6857anomalies = anom = _frommethod('anom') 

6858any = _frommethod('any') 

6859compress = _frommethod('compress', reversed=True) 

6860cumprod = _frommethod('cumprod') 

6861cumsum = _frommethod('cumsum') 

6862copy = _frommethod('copy') 

6863diagonal = _frommethod('diagonal') 

6864harden_mask = _frommethod('harden_mask') 

6865ids = _frommethod('ids') 

6866maximum = _extrema_operation(umath.maximum, greater, maximum_fill_value) 

6867mean = _frommethod('mean') 

6868minimum = _extrema_operation(umath.minimum, less, minimum_fill_value) 

6869nonzero = _frommethod('nonzero') 

6870prod = _frommethod('prod') 

6871product = _frommethod('prod') 

6872ravel = _frommethod('ravel') 

6873repeat = _frommethod('repeat') 

6874shrink_mask = _frommethod('shrink_mask') 

6875soften_mask = _frommethod('soften_mask') 

6876std = _frommethod('std') 

6877sum = _frommethod('sum') 

6878swapaxes = _frommethod('swapaxes') 

6879#take = _frommethod('take') 

6880trace = _frommethod('trace') 

6881var = _frommethod('var') 

6882 

6883count = _frommethod('count') 

6884 

6885def take(a, indices, axis=None, out=None, mode='raise'): 

6886 """ 

6887 """ 

6888 a = masked_array(a) 

6889 return a.take(indices, axis=axis, out=out, mode=mode) 

6890 

6891 

6892def power(a, b, third=None): 

6893 """ 

6894 Returns element-wise base array raised to power from second array. 

6895 

6896 This is the masked array version of `numpy.power`. For details see 

6897 `numpy.power`. 

6898 

6899 See Also 

6900 -------- 

6901 numpy.power 

6902 

6903 Notes 

6904 ----- 

6905 The *out* argument to `numpy.power` is not supported, `third` has to be 

6906 None. 

6907 

6908 Examples 

6909 -------- 

6910 >>> import numpy.ma as ma 

6911 >>> x = [11.2, -3.973, 0.801, -1.41] 

6912 >>> mask = [0, 0, 0, 1] 

6913 >>> masked_x = ma.masked_array(x, mask) 

6914 >>> masked_x 

6915 masked_array(data=[11.2, -3.973, 0.801, --], 

6916 mask=[False, False, False, True], 

6917 fill_value=1e+20) 

6918 >>> ma.power(masked_x, 2) 

6919 masked_array(data=[125.43999999999998, 15.784728999999999, 

6920 0.6416010000000001, --], 

6921 mask=[False, False, False, True], 

6922 fill_value=1e+20) 

6923 >>> y = [-0.5, 2, 0, 17] 

6924 >>> masked_y = ma.masked_array(y, mask) 

6925 >>> masked_y 

6926 masked_array(data=[-0.5, 2.0, 0.0, --], 

6927 mask=[False, False, False, True], 

6928 fill_value=1e+20) 

6929 >>> ma.power(masked_x, masked_y) 

6930 masked_array(data=[0.29880715233359845, 15.784728999999999, 1.0, --], 

6931 mask=[False, False, False, True], 

6932 fill_value=1e+20) 

6933 

6934 """ 

6935 if third is not None: 

6936 raise MaskError("3-argument power not supported.") 

6937 # Get the masks 

6938 ma = getmask(a) 

6939 mb = getmask(b) 

6940 m = mask_or(ma, mb) 

6941 # Get the rawdata 

6942 fa = getdata(a) 

6943 fb = getdata(b) 

6944 # Get the type of the result (so that we preserve subclasses) 

6945 if isinstance(a, MaskedArray): 

6946 basetype = type(a) 

6947 else: 

6948 basetype = MaskedArray 

6949 # Get the result and view it as a (subclass of) MaskedArray 

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

6951 result = np.where(m, fa, umath.power(fa, fb)).view(basetype) 

6952 result._update_from(a) 

6953 # Find where we're in trouble w/ NaNs and Infs 

6954 invalid = np.logical_not(np.isfinite(result.view(ndarray))) 

6955 # Add the initial mask 

6956 if m is not nomask: 

6957 if not result.ndim: 

6958 return masked 

6959 result._mask = np.logical_or(m, invalid) 

6960 # Fix the invalid parts 

6961 if invalid.any(): 

6962 if not result.ndim: 

6963 return masked 

6964 elif result._mask is nomask: 

6965 result._mask = invalid 

6966 result._data[invalid] = result.fill_value 

6967 return result 

6968 

6969argmin = _frommethod('argmin') 

6970argmax = _frommethod('argmax') 

6971 

6972def argsort(a, axis=np._NoValue, kind=None, order=None, endwith=True, fill_value=None): 

6973 "Function version of the eponymous method." 

6974 a = np.asanyarray(a) 

6975 

6976 # 2017-04-11, Numpy 1.13.0, gh-8701: warn on axis default 

6977 if axis is np._NoValue: 

6978 axis = _deprecate_argsort_axis(a) 

6979 

6980 if isinstance(a, MaskedArray): 

6981 return a.argsort(axis=axis, kind=kind, order=order, 

6982 endwith=endwith, fill_value=fill_value) 

6983 else: 

6984 return a.argsort(axis=axis, kind=kind, order=order) 

6985argsort.__doc__ = MaskedArray.argsort.__doc__ 

6986 

6987def sort(a, axis=-1, kind=None, order=None, endwith=True, fill_value=None): 

6988 """ 

6989 Return a sorted copy of the masked array. 

6990 

6991 Equivalent to creating a copy of the array 

6992 and applying the MaskedArray ``sort()`` method. 

6993 

6994 Refer to ``MaskedArray.sort`` for the full documentation 

6995 

6996 See Also 

6997 -------- 

6998 MaskedArray.sort : equivalent method 

6999 """ 

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

7001 if axis is None: 

7002 a = a.flatten() 

7003 axis = 0 

7004 

7005 if isinstance(a, MaskedArray): 

7006 a.sort(axis=axis, kind=kind, order=order, 

7007 endwith=endwith, fill_value=fill_value) 

7008 else: 

7009 a.sort(axis=axis, kind=kind, order=order) 

7010 return a 

7011 

7012 

7013def compressed(x): 

7014 """ 

7015 Return all the non-masked data as a 1-D array. 

7016 

7017 This function is equivalent to calling the "compressed" method of a 

7018 `ma.MaskedArray`, see `ma.MaskedArray.compressed` for details. 

7019 

7020 See Also 

7021 -------- 

7022 ma.MaskedArray.compressed : Equivalent method. 

7023 

7024 """ 

7025 return asanyarray(x).compressed() 

7026 

7027 

7028def concatenate(arrays, axis=0): 

7029 """ 

7030 Concatenate a sequence of arrays along the given axis. 

7031 

7032 Parameters 

7033 ---------- 

7034 arrays : sequence of array_like 

7035 The arrays must have the same shape, except in the dimension 

7036 corresponding to `axis` (the first, by default). 

7037 axis : int, optional 

7038 The axis along which the arrays will be joined. Default is 0. 

7039 

7040 Returns 

7041 ------- 

7042 result : MaskedArray 

7043 The concatenated array with any masked entries preserved. 

7044 

7045 See Also 

7046 -------- 

7047 numpy.concatenate : Equivalent function in the top-level NumPy module. 

7048 

7049 Examples 

7050 -------- 

7051 >>> import numpy.ma as ma 

7052 >>> a = ma.arange(3) 

7053 >>> a[1] = ma.masked 

7054 >>> b = ma.arange(2, 5) 

7055 >>> a 

7056 masked_array(data=[0, --, 2], 

7057 mask=[False, True, False], 

7058 fill_value=999999) 

7059 >>> b 

7060 masked_array(data=[2, 3, 4], 

7061 mask=False, 

7062 fill_value=999999) 

7063 >>> ma.concatenate([a, b]) 

7064 masked_array(data=[0, --, 2, 2, 3, 4], 

7065 mask=[False, True, False, False, False, False], 

7066 fill_value=999999) 

7067 

7068 """ 

7069 d = np.concatenate([getdata(a) for a in arrays], axis) 

7070 rcls = get_masked_subclass(*arrays) 

7071 data = d.view(rcls) 

7072 # Check whether one of the arrays has a non-empty mask. 

7073 for x in arrays: 

7074 if getmask(x) is not nomask: 

7075 break 

7076 else: 

7077 return data 

7078 # OK, so we have to concatenate the masks 

7079 dm = np.concatenate([getmaskarray(a) for a in arrays], axis) 

7080 dm = dm.reshape(d.shape) 

7081 

7082 # If we decide to keep a '_shrinkmask' option, we want to check that 

7083 # all of them are True, and then check for dm.any() 

7084 data._mask = _shrink_mask(dm) 

7085 return data 

7086 

7087 

7088def diag(v, k=0): 

7089 """ 

7090 Extract a diagonal or construct a diagonal array. 

7091 

7092 This function is the equivalent of `numpy.diag` that takes masked 

7093 values into account, see `numpy.diag` for details. 

7094 

7095 See Also 

7096 -------- 

7097 numpy.diag : Equivalent function for ndarrays. 

7098 

7099 Examples 

7100 -------- 

7101  

7102 Create an array with negative values masked: 

7103 

7104 >>> import numpy as np 

7105 >>> x = np.array([[11.2, -3.973, 18], [0.801, -1.41, 12], [7, 33, -12]]) 

7106 >>> masked_x = np.ma.masked_array(x, mask=x < 0) 

7107 >>> masked_x 

7108 masked_array( 

7109 data=[[11.2, --, 18.0], 

7110 [0.801, --, 12.0], 

7111 [7.0, 33.0, --]], 

7112 mask=[[False, True, False], 

7113 [False, True, False], 

7114 [False, False, True]], 

7115 fill_value=1e+20) 

7116 

7117 Isolate the main diagonal from the masked array: 

7118 

7119 >>> np.ma.diag(masked_x) 

7120 masked_array(data=[11.2, --, --], 

7121 mask=[False, True, True], 

7122 fill_value=1e+20) 

7123 

7124 Isolate the first diagonal below the main diagonal: 

7125 

7126 >>> np.ma.diag(masked_x, -1) 

7127 masked_array(data=[0.801, 33.0], 

7128 mask=[False, False], 

7129 fill_value=1e+20) 

7130 

7131 """ 

7132 output = np.diag(v, k).view(MaskedArray) 

7133 if getmask(v) is not nomask: 

7134 output._mask = np.diag(v._mask, k) 

7135 return output 

7136 

7137 

7138def left_shift(a, n): 

7139 """ 

7140 Shift the bits of an integer to the left. 

7141 

7142 This is the masked array version of `numpy.left_shift`, for details 

7143 see that function. 

7144 

7145 See Also 

7146 -------- 

7147 numpy.left_shift 

7148 

7149 """ 

7150 m = getmask(a) 

7151 if m is nomask: 

7152 d = umath.left_shift(filled(a), n) 

7153 return masked_array(d) 

7154 else: 

7155 d = umath.left_shift(filled(a, 0), n) 

7156 return masked_array(d, mask=m) 

7157 

7158 

7159def right_shift(a, n): 

7160 """ 

7161 Shift the bits of an integer to the right. 

7162 

7163 This is the masked array version of `numpy.right_shift`, for details 

7164 see that function. 

7165 

7166 See Also 

7167 -------- 

7168 numpy.right_shift 

7169 

7170 """ 

7171 m = getmask(a) 

7172 if m is nomask: 

7173 d = umath.right_shift(filled(a), n) 

7174 return masked_array(d) 

7175 else: 

7176 d = umath.right_shift(filled(a, 0), n) 

7177 return masked_array(d, mask=m) 

7178 

7179 

7180def put(a, indices, values, mode='raise'): 

7181 """ 

7182 Set storage-indexed locations to corresponding values. 

7183 

7184 This function is equivalent to `MaskedArray.put`, see that method 

7185 for details. 

7186 

7187 See Also 

7188 -------- 

7189 MaskedArray.put 

7190 

7191 """ 

7192 # We can't use 'frommethod', the order of arguments is different 

7193 try: 

7194 return a.put(indices, values, mode=mode) 

7195 except AttributeError: 

7196 return narray(a, copy=False).put(indices, values, mode=mode) 

7197 

7198 

7199def putmask(a, mask, values): # , mode='raise'): 

7200 """ 

7201 Changes elements of an array based on conditional and input values. 

7202 

7203 This is the masked array version of `numpy.putmask`, for details see 

7204 `numpy.putmask`. 

7205 

7206 See Also 

7207 -------- 

7208 numpy.putmask 

7209 

7210 Notes 

7211 ----- 

7212 Using a masked array as `values` will **not** transform a `ndarray` into 

7213 a `MaskedArray`. 

7214 

7215 """ 

7216 # We can't use 'frommethod', the order of arguments is different 

7217 if not isinstance(a, MaskedArray): 

7218 a = a.view(MaskedArray) 

7219 (valdata, valmask) = (getdata(values), getmask(values)) 

7220 if getmask(a) is nomask: 

7221 if valmask is not nomask: 

7222 a._sharedmask = True 

7223 a._mask = make_mask_none(a.shape, a.dtype) 

7224 np.copyto(a._mask, valmask, where=mask) 

7225 elif a._hardmask: 

7226 if valmask is not nomask: 

7227 m = a._mask.copy() 

7228 np.copyto(m, valmask, where=mask) 

7229 a.mask |= m 

7230 else: 

7231 if valmask is nomask: 

7232 valmask = getmaskarray(values) 

7233 np.copyto(a._mask, valmask, where=mask) 

7234 np.copyto(a._data, valdata, where=mask) 

7235 return 

7236 

7237 

7238def transpose(a, axes=None): 

7239 """ 

7240 Permute the dimensions of an array. 

7241 

7242 This function is exactly equivalent to `numpy.transpose`. 

7243 

7244 See Also 

7245 -------- 

7246 numpy.transpose : Equivalent function in top-level NumPy module. 

7247 

7248 Examples 

7249 -------- 

7250 >>> import numpy.ma as ma 

7251 >>> x = ma.arange(4).reshape((2,2)) 

7252 >>> x[1, 1] = ma.masked 

7253 >>> x 

7254 masked_array( 

7255 data=[[0, 1], 

7256 [2, --]], 

7257 mask=[[False, False], 

7258 [False, True]], 

7259 fill_value=999999) 

7260 

7261 >>> ma.transpose(x) 

7262 masked_array( 

7263 data=[[0, 2], 

7264 [1, --]], 

7265 mask=[[False, False], 

7266 [False, True]], 

7267 fill_value=999999) 

7268 """ 

7269 # We can't use 'frommethod', as 'transpose' doesn't take keywords 

7270 try: 

7271 return a.transpose(axes) 

7272 except AttributeError: 

7273 return narray(a, copy=False).transpose(axes).view(MaskedArray) 

7274 

7275 

7276def reshape(a, new_shape, order='C'): 

7277 """ 

7278 Returns an array containing the same data with a new shape. 

7279 

7280 Refer to `MaskedArray.reshape` for full documentation. 

7281 

7282 See Also 

7283 -------- 

7284 MaskedArray.reshape : equivalent function 

7285 

7286 """ 

7287 # We can't use 'frommethod', it whine about some parameters. Dmmit. 

7288 try: 

7289 return a.reshape(new_shape, order=order) 

7290 except AttributeError: 

7291 _tmp = narray(a, copy=False).reshape(new_shape, order=order) 

7292 return _tmp.view(MaskedArray) 

7293 

7294 

7295def resize(x, new_shape): 

7296 """ 

7297 Return a new masked array with the specified size and shape. 

7298 

7299 This is the masked equivalent of the `numpy.resize` function. The new 

7300 array is filled with repeated copies of `x` (in the order that the 

7301 data are stored in memory). If `x` is masked, the new array will be 

7302 masked, and the new mask will be a repetition of the old one. 

7303 

7304 See Also 

7305 -------- 

7306 numpy.resize : Equivalent function in the top level NumPy module. 

7307 

7308 Examples 

7309 -------- 

7310 >>> import numpy.ma as ma 

7311 >>> a = ma.array([[1, 2] ,[3, 4]]) 

7312 >>> a[0, 1] = ma.masked 

7313 >>> a 

7314 masked_array( 

7315 data=[[1, --], 

7316 [3, 4]], 

7317 mask=[[False, True], 

7318 [False, False]], 

7319 fill_value=999999) 

7320 >>> np.resize(a, (3, 3)) 

7321 masked_array( 

7322 data=[[1, 2, 3], 

7323 [4, 1, 2], 

7324 [3, 4, 1]], 

7325 mask=False, 

7326 fill_value=999999) 

7327 >>> ma.resize(a, (3, 3)) 

7328 masked_array( 

7329 data=[[1, --, 3], 

7330 [4, 1, --], 

7331 [3, 4, 1]], 

7332 mask=[[False, True, False], 

7333 [False, False, True], 

7334 [False, False, False]], 

7335 fill_value=999999) 

7336 

7337 A MaskedArray is always returned, regardless of the input type. 

7338 

7339 >>> a = np.array([[1, 2] ,[3, 4]]) 

7340 >>> ma.resize(a, (3, 3)) 

7341 masked_array( 

7342 data=[[1, 2, 3], 

7343 [4, 1, 2], 

7344 [3, 4, 1]], 

7345 mask=False, 

7346 fill_value=999999) 

7347 

7348 """ 

7349 # We can't use _frommethods here, as N.resize is notoriously whiny. 

7350 m = getmask(x) 

7351 if m is not nomask: 

7352 m = np.resize(m, new_shape) 

7353 result = np.resize(x, new_shape).view(get_masked_subclass(x)) 

7354 if result.ndim: 

7355 result._mask = m 

7356 return result 

7357 

7358 

7359def ndim(obj): 

7360 """ 

7361 maskedarray version of the numpy function. 

7362 

7363 """ 

7364 return np.ndim(getdata(obj)) 

7365 

7366ndim.__doc__ = np.ndim.__doc__ 

7367 

7368 

7369def shape(obj): 

7370 "maskedarray version of the numpy function." 

7371 return np.shape(getdata(obj)) 

7372shape.__doc__ = np.shape.__doc__ 

7373 

7374 

7375def size(obj, axis=None): 

7376 "maskedarray version of the numpy function." 

7377 return np.size(getdata(obj), axis) 

7378size.__doc__ = np.size.__doc__ 

7379 

7380 

7381############################################################################## 

7382# Extra functions # 

7383############################################################################## 

7384 

7385 

7386def where(condition, x=_NoValue, y=_NoValue): 

7387 """ 

7388 Return a masked array with elements from `x` or `y`, depending on condition. 

7389 

7390 .. note:: 

7391 When only `condition` is provided, this function is identical to 

7392 `nonzero`. The rest of this documentation covers only the case where 

7393 all three arguments are provided. 

7394 

7395 Parameters 

7396 ---------- 

7397 condition : array_like, bool 

7398 Where True, yield `x`, otherwise yield `y`. 

7399 x, y : array_like, optional 

7400 Values from which to choose. `x`, `y` and `condition` need to be 

7401 broadcastable to some shape. 

7402 

7403 Returns 

7404 ------- 

7405 out : MaskedArray 

7406 An masked array with `masked` elements where the condition is masked, 

7407 elements from `x` where `condition` is True, and elements from `y` 

7408 elsewhere. 

7409 

7410 See Also 

7411 -------- 

7412 numpy.where : Equivalent function in the top-level NumPy module. 

7413 nonzero : The function that is called when x and y are omitted 

7414 

7415 Examples 

7416 -------- 

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

7418 ... [1, 0, 1], 

7419 ... [0, 1, 0]]) 

7420 >>> x 

7421 masked_array( 

7422 data=[[0.0, --, 2.0], 

7423 [--, 4.0, --], 

7424 [6.0, --, 8.0]], 

7425 mask=[[False, True, False], 

7426 [ True, False, True], 

7427 [False, True, False]], 

7428 fill_value=1e+20) 

7429 >>> np.ma.where(x > 5, x, -3.1416) 

7430 masked_array( 

7431 data=[[-3.1416, --, -3.1416], 

7432 [--, -3.1416, --], 

7433 [6.0, --, 8.0]], 

7434 mask=[[False, True, False], 

7435 [ True, False, True], 

7436 [False, True, False]], 

7437 fill_value=1e+20) 

7438 

7439 """ 

7440 

7441 # handle the single-argument case 

7442 missing = (x is _NoValue, y is _NoValue).count(True) 

7443 if missing == 1: 

7444 raise ValueError("Must provide both 'x' and 'y' or neither.") 

7445 if missing == 2: 

7446 return nonzero(condition) 

7447 

7448 # we only care if the condition is true - false or masked pick y 

7449 cf = filled(condition, False) 

7450 xd = getdata(x) 

7451 yd = getdata(y) 

7452 

7453 # we need the full arrays here for correct final dimensions 

7454 cm = getmaskarray(condition) 

7455 xm = getmaskarray(x) 

7456 ym = getmaskarray(y) 

7457 

7458 # deal with the fact that masked.dtype == float64, but we don't actually 

7459 # want to treat it as that. 

7460 if x is masked and y is not masked: 

7461 xd = np.zeros((), dtype=yd.dtype) 

7462 xm = np.ones((), dtype=ym.dtype) 

7463 elif y is masked and x is not masked: 

7464 yd = np.zeros((), dtype=xd.dtype) 

7465 ym = np.ones((), dtype=xm.dtype) 

7466 

7467 data = np.where(cf, xd, yd) 

7468 mask = np.where(cf, xm, ym) 

7469 mask = np.where(cm, np.ones((), dtype=mask.dtype), mask) 

7470 

7471 # collapse the mask, for backwards compatibility 

7472 mask = _shrink_mask(mask) 

7473 

7474 return masked_array(data, mask=mask) 

7475 

7476 

7477def choose(indices, choices, out=None, mode='raise'): 

7478 """ 

7479 Use an index array to construct a new array from a list of choices. 

7480 

7481 Given an array of integers and a list of n choice arrays, this method 

7482 will create a new array that merges each of the choice arrays. Where a 

7483 value in `index` is i, the new array will have the value that choices[i] 

7484 contains in the same place. 

7485 

7486 Parameters 

7487 ---------- 

7488 indices : ndarray of ints 

7489 This array must contain integers in ``[0, n-1]``, where n is the 

7490 number of choices. 

7491 choices : sequence of arrays 

7492 Choice arrays. The index array and all of the choices should be 

7493 broadcastable to the same shape. 

7494 out : array, optional 

7495 If provided, the result will be inserted into this array. It should 

7496 be of the appropriate shape and `dtype`. 

7497 mode : {'raise', 'wrap', 'clip'}, optional 

7498 Specifies how out-of-bounds indices will behave. 

7499 

7500 * 'raise' : raise an error 

7501 * 'wrap' : wrap around 

7502 * 'clip' : clip to the range 

7503 

7504 Returns 

7505 ------- 

7506 merged_array : array 

7507 

7508 See Also 

7509 -------- 

7510 choose : equivalent function 

7511 

7512 Examples 

7513 -------- 

7514 >>> choice = np.array([[1,1,1], [2,2,2], [3,3,3]]) 

7515 >>> a = np.array([2, 1, 0]) 

7516 >>> np.ma.choose(a, choice) 

7517 masked_array(data=[3, 2, 1], 

7518 mask=False, 

7519 fill_value=999999) 

7520 

7521 """ 

7522 def fmask(x): 

7523 "Returns the filled array, or True if masked." 

7524 if x is masked: 

7525 return True 

7526 return filled(x) 

7527 

7528 def nmask(x): 

7529 "Returns the mask, True if ``masked``, False if ``nomask``." 

7530 if x is masked: 

7531 return True 

7532 return getmask(x) 

7533 # Get the indices. 

7534 c = filled(indices, 0) 

7535 # Get the masks. 

7536 masks = [nmask(x) for x in choices] 

7537 data = [fmask(x) for x in choices] 

7538 # Construct the mask 

7539 outputmask = np.choose(c, masks, mode=mode) 

7540 outputmask = make_mask(mask_or(outputmask, getmask(indices)), 

7541 copy=False, shrink=True) 

7542 # Get the choices. 

7543 d = np.choose(c, data, mode=mode, out=out).view(MaskedArray) 

7544 if out is not None: 

7545 if isinstance(out, MaskedArray): 

7546 out.__setmask__(outputmask) 

7547 return out 

7548 d.__setmask__(outputmask) 

7549 return d 

7550 

7551 

7552def round_(a, decimals=0, out=None): 

7553 """ 

7554 Return a copy of a, rounded to 'decimals' places. 

7555 

7556 When 'decimals' is negative, it specifies the number of positions 

7557 to the left of the decimal point. The real and imaginary parts of 

7558 complex numbers are rounded separately. Nothing is done if the 

7559 array is not of float type and 'decimals' is greater than or equal 

7560 to 0. 

7561 

7562 Parameters 

7563 ---------- 

7564 decimals : int 

7565 Number of decimals to round to. May be negative. 

7566 out : array_like 

7567 Existing array to use for output. 

7568 If not given, returns a default copy of a. 

7569 

7570 Notes 

7571 ----- 

7572 If out is given and does not have a mask attribute, the mask of a 

7573 is lost! 

7574 

7575 Examples 

7576 -------- 

7577 >>> import numpy.ma as ma 

7578 >>> x = [11.2, -3.973, 0.801, -1.41] 

7579 >>> mask = [0, 0, 0, 1] 

7580 >>> masked_x = ma.masked_array(x, mask) 

7581 >>> masked_x 

7582 masked_array(data=[11.2, -3.973, 0.801, --], 

7583 mask=[False, False, False, True], 

7584 fill_value=1e+20) 

7585 >>> ma.round_(masked_x) 

7586 masked_array(data=[11.0, -4.0, 1.0, --], 

7587 mask=[False, False, False, True], 

7588 fill_value=1e+20) 

7589 >>> ma.round(masked_x, decimals=1) 

7590 masked_array(data=[11.2, -4.0, 0.8, --], 

7591 mask=[False, False, False, True], 

7592 fill_value=1e+20) 

7593 >>> ma.round_(masked_x, decimals=-1) 

7594 masked_array(data=[10.0, -0.0, 0.0, --], 

7595 mask=[False, False, False, True], 

7596 fill_value=1e+20) 

7597 """ 

7598 if out is None: 

7599 return np.round_(a, decimals, out) 

7600 else: 

7601 np.round_(getdata(a), decimals, out) 

7602 if hasattr(out, '_mask'): 

7603 out._mask = getmask(a) 

7604 return out 

7605round = round_ 

7606 

7607 

7608# Needed by dot, so move here from extras.py. It will still be exported 

7609# from extras.py for compatibility. 

7610def mask_rowcols(a, axis=None): 

7611 """ 

7612 Mask rows and/or columns of a 2D array that contain masked values. 

7613 

7614 Mask whole rows and/or columns of a 2D array that contain 

7615 masked values. The masking behavior is selected using the 

7616 `axis` parameter. 

7617 

7618 - If `axis` is None, rows *and* columns are masked. 

7619 - If `axis` is 0, only rows are masked. 

7620 - If `axis` is 1 or -1, only columns are masked. 

7621 

7622 Parameters 

7623 ---------- 

7624 a : array_like, MaskedArray 

7625 The array to mask. If not a MaskedArray instance (or if no array 

7626 elements are masked). The result is a MaskedArray with `mask` set 

7627 to `nomask` (False). Must be a 2D array. 

7628 axis : int, optional 

7629 Axis along which to perform the operation. If None, applies to a 

7630 flattened version of the array. 

7631 

7632 Returns 

7633 ------- 

7634 a : MaskedArray 

7635 A modified version of the input array, masked depending on the value 

7636 of the `axis` parameter. 

7637 

7638 Raises 

7639 ------ 

7640 NotImplementedError 

7641 If input array `a` is not 2D. 

7642 

7643 See Also 

7644 -------- 

7645 mask_rows : Mask rows of a 2D array that contain masked values. 

7646 mask_cols : Mask cols of a 2D array that contain masked values. 

7647 masked_where : Mask where a condition is met. 

7648 

7649 Notes 

7650 ----- 

7651 The input array's mask is modified by this function. 

7652 

7653 Examples 

7654 -------- 

7655 >>> import numpy.ma as ma 

7656 >>> a = np.zeros((3, 3), dtype=int) 

7657 >>> a[1, 1] = 1 

7658 >>> a 

7659 array([[0, 0, 0], 

7660 [0, 1, 0], 

7661 [0, 0, 0]]) 

7662 >>> a = ma.masked_equal(a, 1) 

7663 >>> a 

7664 masked_array( 

7665 data=[[0, 0, 0], 

7666 [0, --, 0], 

7667 [0, 0, 0]], 

7668 mask=[[False, False, False], 

7669 [False, True, False], 

7670 [False, False, False]], 

7671 fill_value=1) 

7672 >>> ma.mask_rowcols(a) 

7673 masked_array( 

7674 data=[[0, --, 0], 

7675 [--, --, --], 

7676 [0, --, 0]], 

7677 mask=[[False, True, False], 

7678 [ True, True, True], 

7679 [False, True, False]], 

7680 fill_value=1) 

7681 

7682 """ 

7683 a = array(a, subok=False) 

7684 if a.ndim != 2: 

7685 raise NotImplementedError("mask_rowcols works for 2D arrays only.") 

7686 m = getmask(a) 

7687 # Nothing is masked: return a 

7688 if m is nomask or not m.any(): 

7689 return a 

7690 maskedval = m.nonzero() 

7691 a._mask = a._mask.copy() 

7692 if not axis: 

7693 a[np.unique(maskedval[0])] = masked 

7694 if axis in [None, 1, -1]: 

7695 a[:, np.unique(maskedval[1])] = masked 

7696 return a 

7697 

7698 

7699# Include masked dot here to avoid import problems in getting it from 

7700# extras.py. Note that it is not included in __all__, but rather exported 

7701# from extras in order to avoid backward compatibility problems. 

7702def dot(a, b, strict=False, out=None): 

7703 """ 

7704 Return the dot product of two arrays. 

7705 

7706 This function is the equivalent of `numpy.dot` that takes masked values 

7707 into account. Note that `strict` and `out` are in different position 

7708 than in the method version. In order to maintain compatibility with the 

7709 corresponding method, it is recommended that the optional arguments be 

7710 treated as keyword only. At some point that may be mandatory. 

7711 

7712 .. note:: 

7713 Works only with 2-D arrays at the moment. 

7714 

7715 

7716 Parameters 

7717 ---------- 

7718 a, b : masked_array_like 

7719 Inputs arrays. 

7720 strict : bool, optional 

7721 Whether masked data are propagated (True) or set to 0 (False) for 

7722 the computation. Default is False. Propagating the mask means that 

7723 if a masked value appears in a row or column, the whole row or 

7724 column is considered masked. 

7725 out : masked_array, optional 

7726 Output argument. This must have the exact kind that would be returned 

7727 if it was not used. In particular, it must have the right type, must be 

7728 C-contiguous, and its dtype must be the dtype that would be returned 

7729 for `dot(a,b)`. This is a performance feature. Therefore, if these 

7730 conditions are not met, an exception is raised, instead of attempting 

7731 to be flexible. 

7732 

7733 .. versionadded:: 1.10.2 

7734 

7735 See Also 

7736 -------- 

7737 numpy.dot : Equivalent function for ndarrays. 

7738 

7739 Examples 

7740 -------- 

7741 >>> a = np.ma.array([[1, 2, 3], [4, 5, 6]], mask=[[1, 0, 0], [0, 0, 0]]) 

7742 >>> b = np.ma.array([[1, 2], [3, 4], [5, 6]], mask=[[1, 0], [0, 0], [0, 0]]) 

7743 >>> np.ma.dot(a, b) 

7744 masked_array( 

7745 data=[[21, 26], 

7746 [45, 64]], 

7747 mask=[[False, False], 

7748 [False, False]], 

7749 fill_value=999999) 

7750 >>> np.ma.dot(a, b, strict=True) 

7751 masked_array( 

7752 data=[[--, --], 

7753 [--, 64]], 

7754 mask=[[ True, True], 

7755 [ True, False]], 

7756 fill_value=999999) 

7757 

7758 """ 

7759 # !!!: Works only with 2D arrays. There should be a way to get it to run 

7760 # with higher dimension 

7761 if strict and (a.ndim == 2) and (b.ndim == 2): 

7762 a = mask_rowcols(a, 0) 

7763 b = mask_rowcols(b, 1) 

7764 am = ~getmaskarray(a) 

7765 bm = ~getmaskarray(b) 

7766 

7767 if out is None: 

7768 d = np.dot(filled(a, 0), filled(b, 0)) 

7769 m = ~np.dot(am, bm) 

7770 if d.ndim == 0: 

7771 d = np.asarray(d) 

7772 r = d.view(get_masked_subclass(a, b)) 

7773 r.__setmask__(m) 

7774 return r 

7775 else: 

7776 d = np.dot(filled(a, 0), filled(b, 0), out._data) 

7777 if out.mask.shape != d.shape: 

7778 out._mask = np.empty(d.shape, MaskType) 

7779 np.dot(am, bm, out._mask) 

7780 np.logical_not(out._mask, out._mask) 

7781 return out 

7782 

7783 

7784def inner(a, b): 

7785 """ 

7786 Returns the inner product of a and b for arrays of floating point types. 

7787 

7788 Like the generic NumPy equivalent the product sum is over the last dimension 

7789 of a and b. The first argument is not conjugated. 

7790 

7791 """ 

7792 fa = filled(a, 0) 

7793 fb = filled(b, 0) 

7794 if fa.ndim == 0: 

7795 fa.shape = (1,) 

7796 if fb.ndim == 0: 

7797 fb.shape = (1,) 

7798 return np.inner(fa, fb).view(MaskedArray) 

7799inner.__doc__ = doc_note(np.inner.__doc__, 

7800 "Masked values are replaced by 0.") 

7801innerproduct = inner 

7802 

7803 

7804def outer(a, b): 

7805 "maskedarray version of the numpy function." 

7806 fa = filled(a, 0).ravel() 

7807 fb = filled(b, 0).ravel() 

7808 d = np.outer(fa, fb) 

7809 ma = getmask(a) 

7810 mb = getmask(b) 

7811 if ma is nomask and mb is nomask: 

7812 return masked_array(d) 

7813 ma = getmaskarray(a) 

7814 mb = getmaskarray(b) 

7815 m = make_mask(1 - np.outer(1 - ma, 1 - mb), copy=False) 

7816 return masked_array(d, mask=m) 

7817outer.__doc__ = doc_note(np.outer.__doc__, 

7818 "Masked values are replaced by 0.") 

7819outerproduct = outer 

7820 

7821 

7822def _convolve_or_correlate(f, a, v, mode, propagate_mask): 

7823 """ 

7824 Helper function for ma.correlate and ma.convolve 

7825 """ 

7826 if propagate_mask: 

7827 # results which are contributed to by either item in any pair being invalid 

7828 mask = ( 

7829 f(getmaskarray(a), np.ones(np.shape(v), dtype=bool), mode=mode) 

7830 | f(np.ones(np.shape(a), dtype=bool), getmaskarray(v), mode=mode) 

7831 ) 

7832 data = f(getdata(a), getdata(v), mode=mode) 

7833 else: 

7834 # results which are not contributed to by any pair of valid elements 

7835 mask = ~f(~getmaskarray(a), ~getmaskarray(v)) 

7836 data = f(filled(a, 0), filled(v, 0), mode=mode) 

7837 

7838 return masked_array(data, mask=mask) 

7839 

7840 

7841def correlate(a, v, mode='valid', propagate_mask=True): 

7842 """ 

7843 Cross-correlation of two 1-dimensional sequences. 

7844 

7845 Parameters 

7846 ---------- 

7847 a, v : array_like 

7848 Input sequences. 

7849 mode : {'valid', 'same', 'full'}, optional 

7850 Refer to the `np.convolve` docstring. Note that the default 

7851 is 'valid', unlike `convolve`, which uses 'full'. 

7852 propagate_mask : bool 

7853 If True, then a result element is masked if any masked element contributes towards it. 

7854 If False, then a result element is only masked if no non-masked element 

7855 contribute towards it 

7856 

7857 Returns 

7858 ------- 

7859 out : MaskedArray 

7860 Discrete cross-correlation of `a` and `v`. 

7861 

7862 See Also 

7863 -------- 

7864 numpy.correlate : Equivalent function in the top-level NumPy module. 

7865 """ 

7866 return _convolve_or_correlate(np.correlate, a, v, mode, propagate_mask) 

7867 

7868 

7869def convolve(a, v, mode='full', propagate_mask=True): 

7870 """ 

7871 Returns the discrete, linear convolution of two one-dimensional sequences. 

7872 

7873 Parameters 

7874 ---------- 

7875 a, v : array_like 

7876 Input sequences. 

7877 mode : {'valid', 'same', 'full'}, optional 

7878 Refer to the `np.convolve` docstring. 

7879 propagate_mask : bool 

7880 If True, then if any masked element is included in the sum for a result 

7881 element, then the result is masked. 

7882 If False, then the result element is only masked if no non-masked cells 

7883 contribute towards it 

7884 

7885 Returns 

7886 ------- 

7887 out : MaskedArray 

7888 Discrete, linear convolution of `a` and `v`. 

7889 

7890 See Also 

7891 -------- 

7892 numpy.convolve : Equivalent function in the top-level NumPy module. 

7893 """ 

7894 return _convolve_or_correlate(np.convolve, a, v, mode, propagate_mask) 

7895 

7896 

7897def allequal(a, b, fill_value=True): 

7898 """ 

7899 Return True if all entries of a and b are equal, using 

7900 fill_value as a truth value where either or both are masked. 

7901 

7902 Parameters 

7903 ---------- 

7904 a, b : array_like 

7905 Input arrays to compare. 

7906 fill_value : bool, optional 

7907 Whether masked values in a or b are considered equal (True) or not 

7908 (False). 

7909 

7910 Returns 

7911 ------- 

7912 y : bool 

7913 Returns True if the two arrays are equal within the given 

7914 tolerance, False otherwise. If either array contains NaN, 

7915 then False is returned. 

7916 

7917 See Also 

7918 -------- 

7919 all, any 

7920 numpy.ma.allclose 

7921 

7922 Examples 

7923 -------- 

7924 >>> a = np.ma.array([1e10, 1e-7, 42.0], mask=[0, 0, 1]) 

7925 >>> a 

7926 masked_array(data=[10000000000.0, 1e-07, --], 

7927 mask=[False, False, True], 

7928 fill_value=1e+20) 

7929 

7930 >>> b = np.array([1e10, 1e-7, -42.0]) 

7931 >>> b 

7932 array([ 1.00000000e+10, 1.00000000e-07, -4.20000000e+01]) 

7933 >>> np.ma.allequal(a, b, fill_value=False) 

7934 False 

7935 >>> np.ma.allequal(a, b) 

7936 True 

7937 

7938 """ 

7939 m = mask_or(getmask(a), getmask(b)) 

7940 if m is nomask: 

7941 x = getdata(a) 

7942 y = getdata(b) 

7943 d = umath.equal(x, y) 

7944 return d.all() 

7945 elif fill_value: 

7946 x = getdata(a) 

7947 y = getdata(b) 

7948 d = umath.equal(x, y) 

7949 dm = array(d, mask=m, copy=False) 

7950 return dm.filled(True).all(None) 

7951 else: 

7952 return False 

7953 

7954 

7955def allclose(a, b, masked_equal=True, rtol=1e-5, atol=1e-8): 

7956 """ 

7957 Returns True if two arrays are element-wise equal within a tolerance. 

7958 

7959 This function is equivalent to `allclose` except that masked values 

7960 are treated as equal (default) or unequal, depending on the `masked_equal` 

7961 argument. 

7962 

7963 Parameters 

7964 ---------- 

7965 a, b : array_like 

7966 Input arrays to compare. 

7967 masked_equal : bool, optional 

7968 Whether masked values in `a` and `b` are considered equal (True) or not 

7969 (False). They are considered equal by default. 

7970 rtol : float, optional 

7971 Relative tolerance. The relative difference is equal to ``rtol * b``. 

7972 Default is 1e-5. 

7973 atol : float, optional 

7974 Absolute tolerance. The absolute difference is equal to `atol`. 

7975 Default is 1e-8. 

7976 

7977 Returns 

7978 ------- 

7979 y : bool 

7980 Returns True if the two arrays are equal within the given 

7981 tolerance, False otherwise. If either array contains NaN, then 

7982 False is returned. 

7983 

7984 See Also 

7985 -------- 

7986 all, any 

7987 numpy.allclose : the non-masked `allclose`. 

7988 

7989 Notes 

7990 ----- 

7991 If the following equation is element-wise True, then `allclose` returns 

7992 True:: 

7993 

7994 absolute(`a` - `b`) <= (`atol` + `rtol` * absolute(`b`)) 

7995 

7996 Return True if all elements of `a` and `b` are equal subject to 

7997 given tolerances. 

7998 

7999 Examples 

8000 -------- 

8001 >>> a = np.ma.array([1e10, 1e-7, 42.0], mask=[0, 0, 1]) 

8002 >>> a 

8003 masked_array(data=[10000000000.0, 1e-07, --], 

8004 mask=[False, False, True], 

8005 fill_value=1e+20) 

8006 >>> b = np.ma.array([1e10, 1e-8, -42.0], mask=[0, 0, 1]) 

8007 >>> np.ma.allclose(a, b) 

8008 False 

8009 

8010 >>> a = np.ma.array([1e10, 1e-8, 42.0], mask=[0, 0, 1]) 

8011 >>> b = np.ma.array([1.00001e10, 1e-9, -42.0], mask=[0, 0, 1]) 

8012 >>> np.ma.allclose(a, b) 

8013 True 

8014 >>> np.ma.allclose(a, b, masked_equal=False) 

8015 False 

8016 

8017 Masked values are not compared directly. 

8018 

8019 >>> a = np.ma.array([1e10, 1e-8, 42.0], mask=[0, 0, 1]) 

8020 >>> b = np.ma.array([1.00001e10, 1e-9, 42.0], mask=[0, 0, 1]) 

8021 >>> np.ma.allclose(a, b) 

8022 True 

8023 >>> np.ma.allclose(a, b, masked_equal=False) 

8024 False 

8025 

8026 """ 

8027 x = masked_array(a, copy=False) 

8028 y = masked_array(b, copy=False) 

8029 

8030 # make sure y is an inexact type to avoid abs(MIN_INT); will cause 

8031 # casting of x later. 

8032 # NOTE: We explicitly allow timedelta, which used to work. This could 

8033 # possibly be deprecated. See also gh-18286. 

8034 # timedelta works if `atol` is an integer or also a timedelta. 

8035 # Although, the default tolerances are unlikely to be useful 

8036 if y.dtype.kind != "m": 

8037 dtype = np.result_type(y, 1.) 

8038 if y.dtype != dtype: 

8039 y = masked_array(y, dtype=dtype, copy=False) 

8040 

8041 m = mask_or(getmask(x), getmask(y)) 

8042 xinf = np.isinf(masked_array(x, copy=False, mask=m)).filled(False) 

8043 # If we have some infs, they should fall at the same place. 

8044 if not np.all(xinf == filled(np.isinf(y), False)): 

8045 return False 

8046 # No infs at all 

8047 if not np.any(xinf): 

8048 d = filled(less_equal(absolute(x - y), atol + rtol * absolute(y)), 

8049 masked_equal) 

8050 return np.all(d) 

8051 

8052 if not np.all(filled(x[xinf] == y[xinf], masked_equal)): 

8053 return False 

8054 x = x[~xinf] 

8055 y = y[~xinf] 

8056 

8057 d = filled(less_equal(absolute(x - y), atol + rtol * absolute(y)), 

8058 masked_equal) 

8059 

8060 return np.all(d) 

8061 

8062 

8063def asarray(a, dtype=None, order=None): 

8064 """ 

8065 Convert the input to a masked array of the given data-type. 

8066 

8067 No copy is performed if the input is already an `ndarray`. If `a` is 

8068 a subclass of `MaskedArray`, a base class `MaskedArray` is returned. 

8069 

8070 Parameters 

8071 ---------- 

8072 a : array_like 

8073 Input data, in any form that can be converted to a masked array. This 

8074 includes lists, lists of tuples, tuples, tuples of tuples, tuples 

8075 of lists, ndarrays and masked arrays. 

8076 dtype : dtype, optional 

8077 By default, the data-type is inferred from the input data. 

8078 order : {'C', 'F'}, optional 

8079 Whether to use row-major ('C') or column-major ('FORTRAN') memory 

8080 representation. Default is 'C'. 

8081 

8082 Returns 

8083 ------- 

8084 out : MaskedArray 

8085 Masked array interpretation of `a`. 

8086 

8087 See Also 

8088 -------- 

8089 asanyarray : Similar to `asarray`, but conserves subclasses. 

8090 

8091 Examples 

8092 -------- 

8093 >>> x = np.arange(10.).reshape(2, 5) 

8094 >>> x 

8095 array([[0., 1., 2., 3., 4.], 

8096 [5., 6., 7., 8., 9.]]) 

8097 >>> np.ma.asarray(x) 

8098 masked_array( 

8099 data=[[0., 1., 2., 3., 4.], 

8100 [5., 6., 7., 8., 9.]], 

8101 mask=False, 

8102 fill_value=1e+20) 

8103 >>> type(np.ma.asarray(x)) 

8104 <class 'numpy.ma.core.MaskedArray'> 

8105 

8106 """ 

8107 order = order or 'C' 

8108 return masked_array(a, dtype=dtype, copy=False, keep_mask=True, 

8109 subok=False, order=order) 

8110 

8111 

8112def asanyarray(a, dtype=None): 

8113 """ 

8114 Convert the input to a masked array, conserving subclasses. 

8115 

8116 If `a` is a subclass of `MaskedArray`, its class is conserved. 

8117 No copy is performed if the input is already an `ndarray`. 

8118 

8119 Parameters 

8120 ---------- 

8121 a : array_like 

8122 Input data, in any form that can be converted to an array. 

8123 dtype : dtype, optional 

8124 By default, the data-type is inferred from the input data. 

8125 order : {'C', 'F'}, optional 

8126 Whether to use row-major ('C') or column-major ('FORTRAN') memory 

8127 representation. Default is 'C'. 

8128 

8129 Returns 

8130 ------- 

8131 out : MaskedArray 

8132 MaskedArray interpretation of `a`. 

8133 

8134 See Also 

8135 -------- 

8136 asarray : Similar to `asanyarray`, but does not conserve subclass. 

8137 

8138 Examples 

8139 -------- 

8140 >>> x = np.arange(10.).reshape(2, 5) 

8141 >>> x 

8142 array([[0., 1., 2., 3., 4.], 

8143 [5., 6., 7., 8., 9.]]) 

8144 >>> np.ma.asanyarray(x) 

8145 masked_array( 

8146 data=[[0., 1., 2., 3., 4.], 

8147 [5., 6., 7., 8., 9.]], 

8148 mask=False, 

8149 fill_value=1e+20) 

8150 >>> type(np.ma.asanyarray(x)) 

8151 <class 'numpy.ma.core.MaskedArray'> 

8152 

8153 """ 

8154 # workaround for #8666, to preserve identity. Ideally the bottom line 

8155 # would handle this for us. 

8156 if isinstance(a, MaskedArray) and (dtype is None or dtype == a.dtype): 

8157 return a 

8158 return masked_array(a, dtype=dtype, copy=False, keep_mask=True, subok=True) 

8159 

8160 

8161############################################################################## 

8162# Pickling # 

8163############################################################################## 

8164 

8165 

8166def fromfile(file, dtype=float, count=-1, sep=''): 

8167 raise NotImplementedError( 

8168 "fromfile() not yet implemented for a MaskedArray.") 

8169 

8170 

8171def fromflex(fxarray): 

8172 """ 

8173 Build a masked array from a suitable flexible-type array. 

8174 

8175 The input array has to have a data-type with ``_data`` and ``_mask`` 

8176 fields. This type of array is output by `MaskedArray.toflex`. 

8177 

8178 Parameters 

8179 ---------- 

8180 fxarray : ndarray 

8181 The structured input array, containing ``_data`` and ``_mask`` 

8182 fields. If present, other fields are discarded. 

8183 

8184 Returns 

8185 ------- 

8186 result : MaskedArray 

8187 The constructed masked array. 

8188 

8189 See Also 

8190 -------- 

8191 MaskedArray.toflex : Build a flexible-type array from a masked array. 

8192 

8193 Examples 

8194 -------- 

8195 >>> x = np.ma.array(np.arange(9).reshape(3, 3), mask=[0] + [1, 0] * 4) 

8196 >>> rec = x.toflex() 

8197 >>> rec 

8198 array([[(0, False), (1, True), (2, False)], 

8199 [(3, True), (4, False), (5, True)], 

8200 [(6, False), (7, True), (8, False)]], 

8201 dtype=[('_data', '<i8'), ('_mask', '?')]) 

8202 >>> x2 = np.ma.fromflex(rec) 

8203 >>> x2 

8204 masked_array( 

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

8206 [--, 4, --], 

8207 [6, --, 8]], 

8208 mask=[[False, True, False], 

8209 [ True, False, True], 

8210 [False, True, False]], 

8211 fill_value=999999) 

8212 

8213 Extra fields can be present in the structured array but are discarded: 

8214 

8215 >>> dt = [('_data', '<i4'), ('_mask', '|b1'), ('field3', '<f4')] 

8216 >>> rec2 = np.zeros((2, 2), dtype=dt) 

8217 >>> rec2 

8218 array([[(0, False, 0.), (0, False, 0.)], 

8219 [(0, False, 0.), (0, False, 0.)]], 

8220 dtype=[('_data', '<i4'), ('_mask', '?'), ('field3', '<f4')]) 

8221 >>> y = np.ma.fromflex(rec2) 

8222 >>> y 

8223 masked_array( 

8224 data=[[0, 0], 

8225 [0, 0]], 

8226 mask=[[False, False], 

8227 [False, False]], 

8228 fill_value=999999, 

8229 dtype=int32) 

8230 

8231 """ 

8232 return masked_array(fxarray['_data'], mask=fxarray['_mask']) 

8233 

8234 

8235class _convert2ma: 

8236 

8237 """ 

8238 Convert functions from numpy to numpy.ma. 

8239 

8240 Parameters 

8241 ---------- 

8242 _methodname : string 

8243 Name of the method to transform. 

8244 

8245 """ 

8246 __doc__ = None 

8247 

8248 def __init__(self, funcname, np_ret, np_ma_ret, params=None): 

8249 self._func = getattr(np, funcname) 

8250 self.__doc__ = self.getdoc(np_ret, np_ma_ret) 

8251 self._extras = params or {} 

8252 

8253 def getdoc(self, np_ret, np_ma_ret): 

8254 "Return the doc of the function (from the doc of the method)." 

8255 doc = getattr(self._func, '__doc__', None) 

8256 sig = get_object_signature(self._func) 

8257 if doc: 

8258 doc = self._replace_return_type(doc, np_ret, np_ma_ret) 

8259 # Add the signature of the function at the beginning of the doc 

8260 if sig: 

8261 sig = "%s%s\n" % (self._func.__name__, sig) 

8262 doc = sig + doc 

8263 return doc 

8264 

8265 def _replace_return_type(self, doc, np_ret, np_ma_ret): 

8266 """ 

8267 Replace documentation of ``np`` function's return type. 

8268 

8269 Replaces it with the proper type for the ``np.ma`` function. 

8270 

8271 Parameters 

8272 ---------- 

8273 doc : str 

8274 The documentation of the ``np`` method. 

8275 np_ret : str 

8276 The return type string of the ``np`` method that we want to 

8277 replace. (e.g. "out : ndarray") 

8278 np_ma_ret : str 

8279 The return type string of the ``np.ma`` method. 

8280 (e.g. "out : MaskedArray") 

8281 """ 

8282 if np_ret not in doc: 

8283 raise RuntimeError( 

8284 f"Failed to replace `{np_ret}` with `{np_ma_ret}`. " 

8285 f"The documentation string for return type, {np_ret}, is not " 

8286 f"found in the docstring for `np.{self._func.__name__}`. " 

8287 f"Fix the docstring for `np.{self._func.__name__}` or " 

8288 "update the expected string for return type." 

8289 ) 

8290 

8291 return doc.replace(np_ret, np_ma_ret) 

8292 

8293 def __call__(self, *args, **params): 

8294 # Find the common parameters to the call and the definition 

8295 _extras = self._extras 

8296 common_params = set(params).intersection(_extras) 

8297 # Drop the common parameters from the call 

8298 for p in common_params: 

8299 _extras[p] = params.pop(p) 

8300 # Get the result 

8301 result = self._func.__call__(*args, **params).view(MaskedArray) 

8302 if "fill_value" in common_params: 

8303 result.fill_value = _extras.get("fill_value", None) 

8304 if "hardmask" in common_params: 

8305 result._hardmask = bool(_extras.get("hard_mask", False)) 

8306 return result 

8307 

8308 

8309arange = _convert2ma( 

8310 'arange', 

8311 params=dict(fill_value=None, hardmask=False), 

8312 np_ret='arange : ndarray', 

8313 np_ma_ret='arange : MaskedArray', 

8314) 

8315clip = _convert2ma( 

8316 'clip', 

8317 params=dict(fill_value=None, hardmask=False), 

8318 np_ret='clipped_array : ndarray', 

8319 np_ma_ret='clipped_array : MaskedArray', 

8320) 

8321diff = _convert2ma( 

8322 'diff', 

8323 params=dict(fill_value=None, hardmask=False), 

8324 np_ret='diff : ndarray', 

8325 np_ma_ret='diff : MaskedArray', 

8326) 

8327empty = _convert2ma( 

8328 'empty', 

8329 params=dict(fill_value=None, hardmask=False), 

8330 np_ret='out : ndarray', 

8331 np_ma_ret='out : MaskedArray', 

8332) 

8333empty_like = _convert2ma( 

8334 'empty_like', 

8335 np_ret='out : ndarray', 

8336 np_ma_ret='out : MaskedArray', 

8337) 

8338frombuffer = _convert2ma( 

8339 'frombuffer', 

8340 np_ret='out : ndarray', 

8341 np_ma_ret='out: MaskedArray', 

8342) 

8343fromfunction = _convert2ma( 

8344 'fromfunction', 

8345 np_ret='fromfunction : any', 

8346 np_ma_ret='fromfunction: MaskedArray', 

8347) 

8348identity = _convert2ma( 

8349 'identity', 

8350 params=dict(fill_value=None, hardmask=False), 

8351 np_ret='out : ndarray', 

8352 np_ma_ret='out : MaskedArray', 

8353) 

8354indices = _convert2ma( 

8355 'indices', 

8356 params=dict(fill_value=None, hardmask=False), 

8357 np_ret='grid : one ndarray or tuple of ndarrays', 

8358 np_ma_ret='grid : one MaskedArray or tuple of MaskedArrays', 

8359) 

8360ones = _convert2ma( 

8361 'ones', 

8362 params=dict(fill_value=None, hardmask=False), 

8363 np_ret='out : ndarray', 

8364 np_ma_ret='out : MaskedArray', 

8365) 

8366ones_like = _convert2ma( 

8367 'ones_like', 

8368 np_ret='out : ndarray', 

8369 np_ma_ret='out : MaskedArray', 

8370) 

8371squeeze = _convert2ma( 

8372 'squeeze', 

8373 params=dict(fill_value=None, hardmask=False), 

8374 np_ret='squeezed : ndarray', 

8375 np_ma_ret='squeezed : MaskedArray', 

8376) 

8377zeros = _convert2ma( 

8378 'zeros', 

8379 params=dict(fill_value=None, hardmask=False), 

8380 np_ret='out : ndarray', 

8381 np_ma_ret='out : MaskedArray', 

8382) 

8383zeros_like = _convert2ma( 

8384 'zeros_like', 

8385 np_ret='out : ndarray', 

8386 np_ma_ret='out : MaskedArray', 

8387) 

8388 

8389 

8390def append(a, b, axis=None): 

8391 """Append values to the end of an array. 

8392 

8393 .. versionadded:: 1.9.0 

8394 

8395 Parameters 

8396 ---------- 

8397 a : array_like 

8398 Values are appended to a copy of this array. 

8399 b : array_like 

8400 These values are appended to a copy of `a`. It must be of the 

8401 correct shape (the same shape as `a`, excluding `axis`). If `axis` 

8402 is not specified, `b` can be any shape and will be flattened 

8403 before use. 

8404 axis : int, optional 

8405 The axis along which `v` are appended. If `axis` is not given, 

8406 both `a` and `b` are flattened before use. 

8407 

8408 Returns 

8409 ------- 

8410 append : MaskedArray 

8411 A copy of `a` with `b` appended to `axis`. Note that `append` 

8412 does not occur in-place: a new array is allocated and filled. If 

8413 `axis` is None, the result is a flattened array. 

8414 

8415 See Also 

8416 -------- 

8417 numpy.append : Equivalent function in the top-level NumPy module. 

8418 

8419 Examples 

8420 -------- 

8421 >>> import numpy.ma as ma 

8422 >>> a = ma.masked_values([1, 2, 3], 2) 

8423 >>> b = ma.masked_values([[4, 5, 6], [7, 8, 9]], 7) 

8424 >>> ma.append(a, b) 

8425 masked_array(data=[1, --, 3, 4, 5, 6, --, 8, 9], 

8426 mask=[False, True, False, False, False, False, True, False, 

8427 False], 

8428 fill_value=999999) 

8429 """ 

8430 return concatenate([a, b], axis)