Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1""" 

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

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 operator 

25import warnings 

26import textwrap 

27import re 

28from functools import reduce 

29 

30import numpy as np 

31import numpy.core.umath as umath 

32import numpy.core.numerictypes as ntypes 

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

34from numpy import array as narray 

35from numpy.lib.function_base import angle 

36from numpy.compat import ( 

37 getargspec, formatargspec, long, unicode, bytes 

38 ) 

39from numpy import expand_dims 

40from numpy.core.numeric import normalize_axis_tuple 

41from numpy.core._internal import recursive 

42from numpy.compat import pickle 

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', 'outer', 'outerproduct', 'power', 'prod', 

73 'product', 'ptp', 'put', 'putmask', 'ravel', 'remainder', 

74 'repeat', 'reshape', 'resize', 'right_shift', 'round', 'round_', 

75 'set_fill_value', 'shape', 'sin', 'sinh', 'size', 'soften_mask', 

76 'sometrue', 'sort', 'sqrt', 'squeeze', 'std', 'subtract', 'sum', 

77 'swapaxes', 'take', 'tan', 'tanh', 'trace', 'transpose', 'true_divide', 

78 'var', 'where', 'zeros', 

79 ] 

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*?-----', initialdoc) 

126 

127 notedoc = """\ 

128Notes 

129 ----- 

130 %s""" % note 

131 

132 if len(notesplit) > 1: 

133 notedoc = '\n\n ' + notedoc + '\n' 

134 

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

136 

137 

138def get_object_signature(obj): 

139 """ 

140 Get the signature from obj 

141 

142 """ 

143 try: 

144 sig = formatargspec(*getargspec(obj)) 

145 except TypeError: 

146 sig = '' 

147 return sig 

148 

149 

150############################################################################### 

151# Exceptions # 

152############################################################################### 

153 

154 

155class MAError(Exception): 

156 """ 

157 Class for masked array related errors. 

158 

159 """ 

160 pass 

161 

162 

163class MaskError(MAError): 

164 """ 

165 Class for mask related errors. 

166 

167 """ 

168 pass 

169 

170 

171############################################################################### 

172# Filling options # 

173############################################################################### 

174 

175 

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

177default_filler = {'b': True, 

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

179 'f': 1.e20, 

180 'i': 999999, 

181 'O': '?', 

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

183 'u': 999999, 

184 'V': b'???', 

185 'U': u'N/A' 

186 } 

187 

188# Add datetime64 and timedelta64 types 

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

190 "fs", "as"]: 

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

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

193 

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

195 np.csingle, np.cdouble, np.clongdouble] 

196max_filler = ntypes._minvals 

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

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

199 

200min_filler = ntypes._maxvals 

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

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

203 

204del float_types_list 

205 

206def _recursive_fill_value(dtype, f): 

207 """ 

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

209 """ 

210 if dtype.names is not None: 

211 vals = tuple(_recursive_fill_value(dtype[name], f) for name in dtype.names) 

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

213 elif dtype.subdtype: 

214 subtype, shape = dtype.subdtype 

215 subval = _recursive_fill_value(subtype, f) 

216 return np.full(shape, subval) 

217 else: 

218 return f(dtype) 

219 

220 

221def _get_dtype_of(obj): 

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

223 if isinstance(obj, np.dtype): 

224 return obj 

225 elif hasattr(obj, 'dtype'): 

226 return obj.dtype 

227 else: 

228 return np.asanyarray(obj).dtype 

229 

230 

231def default_fill_value(obj): 

232 """ 

233 Return the default fill value for the argument object. 

234 

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

236 array or the type of the input scalar: 

237 

238 ======== ======== 

239 datatype default 

240 ======== ======== 

241 bool True 

242 int 999999 

243 float 1.e20 

244 complex 1.e20+0j 

245 object '?' 

246 string 'N/A' 

247 ======== ======== 

248 

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

250 default fill value for its type. 

251 

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

253 the default scalar fill value. 

254 

255 Parameters 

256 ---------- 

257 obj : ndarray, dtype or scalar 

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

259 is returned. 

260 

261 Returns 

262 ------- 

263 fill_value : scalar 

264 The default fill value. 

265 

266 Examples 

267 -------- 

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

269 999999 

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

271 1e+20 

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

273 (1e+20+0j) 

274 

275 """ 

276 def _scalar_fill_value(dtype): 

277 if dtype.kind in 'Mm': 

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

279 else: 

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

281 

282 dtype = _get_dtype_of(obj) 

283 return _recursive_fill_value(dtype, _scalar_fill_value) 

284 

285 

286def _extremum_fill_value(obj, extremum, extremum_name): 

287 

288 def _scalar_fill_value(dtype): 

289 try: 

290 return extremum[dtype] 

291 except KeyError as e: 

292 raise TypeError( 

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

294 ) from None 

295 

296 dtype = _get_dtype_of(obj) 

297 return _recursive_fill_value(dtype, _scalar_fill_value) 

298 

299 

300def minimum_fill_value(obj): 

301 """ 

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

303 

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

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

306 

307 Parameters 

308 ---------- 

309 obj : ndarray, dtype or scalar 

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

311 

312 Returns 

313 ------- 

314 val : scalar 

315 The maximum representable value. 

316 

317 Raises 

318 ------ 

319 TypeError 

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

321 

322 See Also 

323 -------- 

324 maximum_fill_value : The inverse function. 

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

326 MaskedArray.fill_value : Return current fill value. 

327 

328 Examples 

329 -------- 

330 >>> import numpy.ma as ma 

331 >>> a = np.int8() 

332 >>> ma.minimum_fill_value(a) 

333 127 

334 >>> a = np.int32() 

335 >>> ma.minimum_fill_value(a) 

336 2147483647 

337 

338 An array of numeric data can also be passed. 

339 

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

341 >>> ma.minimum_fill_value(a) 

342 127 

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

344 >>> ma.minimum_fill_value(a) 

345 inf 

346 

347 """ 

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

349 

350 

351def maximum_fill_value(obj): 

352 """ 

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

354 

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

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

357 

358 Parameters 

359 ---------- 

360 obj : ndarray, dtype or scalar 

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

362 

363 Returns 

364 ------- 

365 val : scalar 

366 The minimum representable value. 

367 

368 Raises 

369 ------ 

370 TypeError 

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

372 

373 See Also 

374 -------- 

375 minimum_fill_value : The inverse function. 

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

377 MaskedArray.fill_value : Return current fill value. 

378 

379 Examples 

380 -------- 

381 >>> import numpy.ma as ma 

382 >>> a = np.int8() 

383 >>> ma.maximum_fill_value(a) 

384 -128 

385 >>> a = np.int32() 

386 >>> ma.maximum_fill_value(a) 

387 -2147483648 

388 

389 An array of numeric data can also be passed. 

390 

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

392 >>> ma.maximum_fill_value(a) 

393 -128 

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

395 >>> ma.maximum_fill_value(a) 

396 -inf 

397 

398 """ 

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

400 

401 

402def _recursive_set_fill_value(fillvalue, dt): 

403 """ 

404 Create a fill value for a structured dtype. 

405 

406 Parameters 

407 ---------- 

408 fillvalue: scalar or array_like 

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

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

411 dt: dtype 

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

413 

414 Returns 

415 ------- 

416 val: tuple 

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

418 

419 """ 

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

421 output_value = [] 

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

423 cdtype = dt[name] 

424 if cdtype.subdtype: 

425 cdtype = cdtype.subdtype[0] 

426 

427 if cdtype.names is not None: 

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

429 else: 

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

431 return tuple(output_value) 

432 

433 

434def _check_fill_value(fill_value, ndtype): 

435 """ 

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

437 

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

439 

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

441 

442 The result is always a 0d array. 

443 

444 """ 

445 ndtype = np.dtype(ndtype) 

446 if fill_value is None: 

447 fill_value = default_fill_value(ndtype) 

448 elif ndtype.names is not None: 

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

450 try: 

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

452 except ValueError: 

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

454 raise ValueError(err_msg % (fill_value, ndtype)) 

455 else: 

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

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

458 dtype=ndtype) 

459 else: 

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

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

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

463 raise TypeError(err_msg % ndtype) 

464 else: 

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

466 # Also in case of converting string arrays. 

467 try: 

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

469 except (OverflowError, ValueError): 

470 # Raise TypeError instead of OverflowError or ValueError. 

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

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

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

474 raise TypeError(err_msg % (fill_value, ndtype)) 

475 return np.array(fill_value) 

476 

477 

478def set_fill_value(a, fill_value): 

479 """ 

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

481 

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

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

484 doing anything. 

485 

486 Parameters 

487 ---------- 

488 a : array_like 

489 Input array. 

490 fill_value : dtype 

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

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

493 

494 Returns 

495 ------- 

496 None 

497 Nothing returned by this function. 

498 

499 See Also 

500 -------- 

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

502 MaskedArray.fill_value : Return current fill value. 

503 MaskedArray.set_fill_value : Equivalent method. 

504 

505 Examples 

506 -------- 

507 >>> import numpy.ma as ma 

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

509 >>> a 

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

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

512 >>> a 

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

514 mask=[ True, True, True, False, False], 

515 fill_value=999999) 

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

517 >>> a 

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

519 mask=[ True, True, True, False, False], 

520 fill_value=-999) 

521 

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

523 

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

525 >>> a 

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

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

528 >>> a 

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

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

531 >>> a 

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

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

534 >>> a 

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

536 

537 """ 

538 if isinstance(a, MaskedArray): 

539 a.set_fill_value(fill_value) 

540 return 

541 

542 

543def get_fill_value(a): 

544 """ 

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

546 default filling value for that type. 

547 

548 """ 

549 if isinstance(a, MaskedArray): 

550 result = a.fill_value 

551 else: 

552 result = default_fill_value(a) 

553 return result 

554 

555 

556def common_fill_value(a, b): 

557 """ 

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

559 

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

561 otherwise return None. 

562 

563 Parameters 

564 ---------- 

565 a, b : MaskedArray 

566 The masked arrays for which to compare fill values. 

567 

568 Returns 

569 ------- 

570 fill_value : scalar or None 

571 The common fill value, or None. 

572 

573 Examples 

574 -------- 

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

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

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

578 3.0 

579 

580 """ 

581 t1 = get_fill_value(a) 

582 t2 = get_fill_value(b) 

583 if t1 == t2: 

584 return t1 

585 return None 

586 

587 

588def filled(a, fill_value=None): 

589 """ 

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

591 

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

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

594 ``a.fill_value``. 

595 

596 Parameters 

597 ---------- 

598 a : MaskedArray or array_like 

599 An input object. 

600 fill_value : array_like, optional. 

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

602 resulting filled array should be broadcastable 

603 over input array. Default is None. 

604 

605 Returns 

606 ------- 

607 a : ndarray 

608 The filled array. 

609 

610 See Also 

611 -------- 

612 compressed 

613 

614 Examples 

615 -------- 

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

617 ... [1, 0, 0], 

618 ... [0, 0, 0]]) 

619 >>> x.filled() 

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

621 [999999, 4, 5], 

622 [ 6, 7, 8]]) 

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

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

625 [333, 4, 5], 

626 [ 6, 7, 8]]) 

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

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

629 [0, 4, 5], 

630 [6, 7, 8]]) 

631 

632 """ 

633 if hasattr(a, 'filled'): 

634 return a.filled(fill_value) 

635 

636 elif isinstance(a, ndarray): 

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

638 return a 

639 elif isinstance(a, dict): 

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

641 else: 

642 return np.array(a) 

643 

644 

645def get_masked_subclass(*arrays): 

646 """ 

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

648 

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

650 

651 """ 

652 if len(arrays) == 1: 

653 arr = arrays[0] 

654 if isinstance(arr, MaskedArray): 

655 rcls = type(arr) 

656 else: 

657 rcls = MaskedArray 

658 else: 

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

660 rcls = arrcls[0] 

661 if not issubclass(rcls, MaskedArray): 

662 rcls = MaskedArray 

663 for cls in arrcls[1:]: 

664 if issubclass(cls, rcls): 

665 rcls = cls 

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

667 if rcls.__name__ == 'MaskedConstant': 

668 return MaskedArray 

669 return rcls 

670 

671 

672def getdata(a, subok=True): 

673 """ 

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

675 

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

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

678 

679 Parameters 

680 ---------- 

681 a : array_like 

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

683 subok : bool 

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

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

686 

687 See Also 

688 -------- 

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

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

691 

692 Examples 

693 -------- 

694 >>> import numpy.ma as ma 

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

696 >>> a 

697 masked_array( 

698 data=[[1, --], 

699 [3, 4]], 

700 mask=[[False, True], 

701 [False, False]], 

702 fill_value=2) 

703 >>> ma.getdata(a) 

704 array([[1, 2], 

705 [3, 4]]) 

706 

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

708 

709 >>> a.data 

710 array([[1, 2], 

711 [3, 4]]) 

712 

713 """ 

714 try: 

715 data = a._data 

716 except AttributeError: 

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

718 if not subok: 

719 return data.view(ndarray) 

720 return data 

721 

722 

723get_data = getdata 

724 

725 

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

727 """ 

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

729 

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

731 

732 Parameters 

733 ---------- 

734 a : array_like 

735 Input array, a (subclass of) ndarray. 

736 mask : sequence, optional 

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

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

739 copy : bool, optional 

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

741 Default is True. 

742 fill_value : scalar, optional 

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

744 the ``a.fill_value`` is used. 

745 

746 Returns 

747 ------- 

748 b : MaskedArray 

749 The input array with invalid entries fixed. 

750 

751 Notes 

752 ----- 

753 A copy is performed by default. 

754 

755 Examples 

756 -------- 

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

758 >>> x 

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

760 mask=[ True, False, False, False], 

761 fill_value=1e+20) 

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

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

764 mask=[ True, False, True, True], 

765 fill_value=1e+20) 

766 

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

768 >>> fixed.data 

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

770 >>> x.data 

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

772 

773 """ 

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

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

776 if not invalid.any(): 

777 return a 

778 a._mask |= invalid 

779 if fill_value is None: 

780 fill_value = a.fill_value 

781 a._data[invalid] = fill_value 

782 return a 

783 

784def is_string_or_list_of_strings(val): 

785 return (isinstance(val, str) or 

786 (isinstance(val, list) and val and 

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

788 

789############################################################################### 

790# Ufuncs # 

791############################################################################### 

792 

793 

794ufunc_domain = {} 

795ufunc_fills = {} 

796 

797 

798class _DomainCheckInterval: 

799 """ 

800 Define a valid interval, so that : 

801 

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

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

804 

805 """ 

806 

807 def __init__(self, a, b): 

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

809 if a > b: 

810 (a, b) = (b, a) 

811 self.a = a 

812 self.b = b 

813 

814 def __call__(self, x): 

815 "Execute the call behavior." 

816 # nans at masked positions cause RuntimeWarnings, even though 

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

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

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

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

821 

822 

823class _DomainTan: 

824 """ 

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

826 

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

828 

829 """ 

830 

831 def __init__(self, eps): 

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

833 self.eps = eps 

834 

835 def __call__(self, x): 

836 "Executes the call behavior." 

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

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

839 

840 

841class _DomainSafeDivide: 

842 """ 

843 Define a domain for safe division. 

844 

845 """ 

846 

847 def __init__(self, tolerance=None): 

848 self.tolerance = tolerance 

849 

850 def __call__(self, a, b): 

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

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

853 # component of numpy's import time. 

854 if self.tolerance is None: 

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

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

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

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

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

860 

861 

862class _DomainGreater: 

863 """ 

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

865 

866 """ 

867 

868 def __init__(self, critical_value): 

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

870 self.critical_value = critical_value 

871 

872 def __call__(self, x): 

873 "Executes the call behavior." 

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

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

876 

877 

878class _DomainGreaterEqual: 

879 """ 

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

881 

882 """ 

883 

884 def __init__(self, critical_value): 

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

886 self.critical_value = critical_value 

887 

888 def __call__(self, x): 

889 "Executes the call behavior." 

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

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

892 

893 

894class _MaskedUFunc: 

895 def __init__(self, ufunc): 

896 self.f = ufunc 

897 self.__doc__ = ufunc.__doc__ 

898 self.__name__ = ufunc.__name__ 

899 

900 def __str__(self): 

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

902 

903 

904class _MaskedUnaryOperation(_MaskedUFunc): 

905 """ 

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

907 pre-masked. 

908 

909 Parameters 

910 ---------- 

911 mufunc : callable 

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

913 as ``_MaskedUnaryOperation.f``. 

914 fill : scalar, optional 

915 Filling value, default is 0. 

916 domain : class instance 

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

918 classes. Default is None. 

919 

920 """ 

921 

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

923 super(_MaskedUnaryOperation, self).__init__(mufunc) 

924 self.fill = fill 

925 self.domain = domain 

926 ufunc_domain[mufunc] = domain 

927 ufunc_fills[mufunc] = fill 

928 

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

930 """ 

931 Execute the call behavior. 

932 

933 """ 

934 d = getdata(a) 

935 # Deal with domain 

936 if self.domain is not None: 

937 # Case 1.1. : Domained function 

938 # nans at masked positions cause RuntimeWarnings, even though 

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

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

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

942 # Make a mask 

943 m = ~umath.isfinite(result) 

944 m |= self.domain(d) 

945 m |= getmask(a) 

946 else: 

947 # Case 1.2. : Function without a domain 

948 # Get the result and the mask 

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

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

951 m = getmask(a) 

952 

953 if not result.ndim: 

954 # Case 2.1. : The result is scalarscalar 

955 if m: 

956 return masked 

957 return result 

958 

959 if m is not nomask: 

960 # Case 2.2. The result is an array 

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

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

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

964 

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

966 # equal) 

967 try: 

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

969 except TypeError: 

970 pass 

971 # Transform to 

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

973 masked_result._mask = m 

974 masked_result._update_from(a) 

975 return masked_result 

976 

977 

978class _MaskedBinaryOperation(_MaskedUFunc): 

979 """ 

980 Define masked version of binary operations, where invalid 

981 values are pre-masked. 

982 

983 Parameters 

984 ---------- 

985 mbfunc : function 

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

987 as ``_MaskedBinaryOperation.f``. 

988 domain : class instance 

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

990 classes. Default is None. 

991 fillx : scalar, optional 

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

993 filly : scalar, optional 

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

995 

996 """ 

997 

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

999 """ 

1000 abfunc(fillx, filly) must be defined. 

1001 

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

1003 

1004 """ 

1005 super(_MaskedBinaryOperation, self).__init__(mbfunc) 

1006 self.fillx = fillx 

1007 self.filly = filly 

1008 ufunc_domain[mbfunc] = None 

1009 ufunc_fills[mbfunc] = (fillx, filly) 

1010 

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

1012 """ 

1013 Execute the call behavior. 

1014 

1015 """ 

1016 # Get the data, as ndarray 

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

1018 # Get the result 

1019 with np.errstate(): 

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

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

1022 # Get the mask for the result 

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

1024 if ma is nomask: 

1025 if mb is nomask: 

1026 m = nomask 

1027 else: 

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

1029 elif mb is nomask: 

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

1031 else: 

1032 m = umath.logical_or(ma, mb) 

1033 

1034 # Case 1. : scalar 

1035 if not result.ndim: 

1036 if m: 

1037 return masked 

1038 return result 

1039 

1040 # Case 2. : array 

1041 # Revert result to da where masked 

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

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

1044 try: 

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

1046 except Exception: 

1047 pass 

1048 

1049 # Transforms to a (subclass of) MaskedArray 

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

1051 masked_result._mask = m 

1052 if isinstance(a, MaskedArray): 

1053 masked_result._update_from(a) 

1054 elif isinstance(b, MaskedArray): 

1055 masked_result._update_from(b) 

1056 return masked_result 

1057 

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

1059 """ 

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

1061 

1062 """ 

1063 tclass = get_masked_subclass(target) 

1064 m = getmask(target) 

1065 t = filled(target, self.filly) 

1066 if t.shape == (): 

1067 t = t.reshape(1) 

1068 if m is not nomask: 

1069 m = make_mask(m, copy=True) 

1070 m.shape = (1,) 

1071 

1072 if m is nomask: 

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

1074 mr = nomask 

1075 else: 

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

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

1078 

1079 if not tr.shape: 

1080 if mr: 

1081 return masked 

1082 else: 

1083 return tr 

1084 masked_tr = tr.view(tclass) 

1085 masked_tr._mask = mr 

1086 return masked_tr 

1087 

1088 def outer(self, a, b): 

1089 """ 

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

1091 

1092 """ 

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

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

1095 ma = getmask(a) 

1096 mb = getmask(b) 

1097 if ma is nomask and mb is nomask: 

1098 m = nomask 

1099 else: 

1100 ma = getmaskarray(a) 

1101 mb = getmaskarray(b) 

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

1103 if (not m.ndim) and m: 

1104 return masked 

1105 if m is not nomask: 

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

1107 if not d.shape: 

1108 return d 

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

1110 masked_d._mask = m 

1111 return masked_d 

1112 

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

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

1115 value. 

1116 

1117 """ 

1118 tclass = get_masked_subclass(target) 

1119 t = filled(target, self.filly) 

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

1121 masked_result = result.view(tclass) 

1122 return masked_result 

1123 

1124 

1125 

1126class _DomainedBinaryOperation(_MaskedUFunc): 

1127 """ 

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

1129 

1130 They have no reduce, outer or accumulate. 

1131 

1132 Parameters 

1133 ---------- 

1134 mbfunc : function 

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

1136 as ``_DomainedBinaryOperation.f``. 

1137 domain : class instance 

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

1139 classes. 

1140 fillx : scalar, optional 

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

1142 filly : scalar, optional 

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

1144 

1145 """ 

1146 

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

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

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

1150 """ 

1151 super(_DomainedBinaryOperation, self).__init__(dbfunc) 

1152 self.domain = domain 

1153 self.fillx = fillx 

1154 self.filly = filly 

1155 ufunc_domain[dbfunc] = domain 

1156 ufunc_fills[dbfunc] = (fillx, filly) 

1157 

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

1159 "Execute the call behavior." 

1160 # Get the data 

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

1162 # Get the result 

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

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

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

1166 m = ~umath.isfinite(result) 

1167 m |= getmask(a) 

1168 m |= getmask(b) 

1169 # Apply the domain 

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

1171 if domain is not None: 

1172 m |= domain(da, db) 

1173 # Take care of the scalar case first 

1174 if not m.ndim: 

1175 if m: 

1176 return masked 

1177 else: 

1178 return result 

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

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

1181 try: 

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

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

1184 masked_da = umath.multiply(m, da) 

1185 # only add back if it can be cast safely 

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

1187 result += masked_da 

1188 except Exception: 

1189 pass 

1190 

1191 # Transforms to a (subclass of) MaskedArray 

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

1193 masked_result._mask = m 

1194 if isinstance(a, MaskedArray): 

1195 masked_result._update_from(a) 

1196 elif isinstance(b, MaskedArray): 

1197 masked_result._update_from(b) 

1198 return masked_result 

1199 

1200 

1201# Unary ufuncs 

1202exp = _MaskedUnaryOperation(umath.exp) 

1203conjugate = _MaskedUnaryOperation(umath.conjugate) 

1204sin = _MaskedUnaryOperation(umath.sin) 

1205cos = _MaskedUnaryOperation(umath.cos) 

1206arctan = _MaskedUnaryOperation(umath.arctan) 

1207arcsinh = _MaskedUnaryOperation(umath.arcsinh) 

1208sinh = _MaskedUnaryOperation(umath.sinh) 

1209cosh = _MaskedUnaryOperation(umath.cosh) 

1210tanh = _MaskedUnaryOperation(umath.tanh) 

1211abs = absolute = _MaskedUnaryOperation(umath.absolute) 

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

1213fabs = _MaskedUnaryOperation(umath.fabs) 

1214negative = _MaskedUnaryOperation(umath.negative) 

1215floor = _MaskedUnaryOperation(umath.floor) 

1216ceil = _MaskedUnaryOperation(umath.ceil) 

1217around = _MaskedUnaryOperation(np.round_) 

1218logical_not = _MaskedUnaryOperation(umath.logical_not) 

1219 

1220# Domained unary ufuncs 

1221sqrt = _MaskedUnaryOperation(umath.sqrt, 0.0, 

1222 _DomainGreaterEqual(0.0)) 

1223log = _MaskedUnaryOperation(umath.log, 1.0, 

1224 _DomainGreater(0.0)) 

1225log2 = _MaskedUnaryOperation(umath.log2, 1.0, 

1226 _DomainGreater(0.0)) 

1227log10 = _MaskedUnaryOperation(umath.log10, 1.0, 

1228 _DomainGreater(0.0)) 

1229tan = _MaskedUnaryOperation(umath.tan, 0.0, 

1230 _DomainTan(1e-35)) 

1231arcsin = _MaskedUnaryOperation(umath.arcsin, 0.0, 

1232 _DomainCheckInterval(-1.0, 1.0)) 

1233arccos = _MaskedUnaryOperation(umath.arccos, 0.0, 

1234 _DomainCheckInterval(-1.0, 1.0)) 

1235arccosh = _MaskedUnaryOperation(umath.arccosh, 1.0, 

1236 _DomainGreaterEqual(1.0)) 

1237arctanh = _MaskedUnaryOperation(umath.arctanh, 0.0, 

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

1239 

1240# Binary ufuncs 

1241add = _MaskedBinaryOperation(umath.add) 

1242subtract = _MaskedBinaryOperation(umath.subtract) 

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

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

1245equal = _MaskedBinaryOperation(umath.equal) 

1246equal.reduce = None 

1247not_equal = _MaskedBinaryOperation(umath.not_equal) 

1248not_equal.reduce = None 

1249less_equal = _MaskedBinaryOperation(umath.less_equal) 

1250less_equal.reduce = None 

1251greater_equal = _MaskedBinaryOperation(umath.greater_equal) 

1252greater_equal.reduce = None 

1253less = _MaskedBinaryOperation(umath.less) 

1254less.reduce = None 

1255greater = _MaskedBinaryOperation(umath.greater) 

1256greater.reduce = None 

1257logical_and = _MaskedBinaryOperation(umath.logical_and) 

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

1259logical_or = _MaskedBinaryOperation(umath.logical_or) 

1260sometrue = logical_or.reduce 

1261logical_xor = _MaskedBinaryOperation(umath.logical_xor) 

1262bitwise_and = _MaskedBinaryOperation(umath.bitwise_and) 

1263bitwise_or = _MaskedBinaryOperation(umath.bitwise_or) 

1264bitwise_xor = _MaskedBinaryOperation(umath.bitwise_xor) 

1265hypot = _MaskedBinaryOperation(umath.hypot) 

1266 

1267# Domained binary ufuncs 

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

1269true_divide = _DomainedBinaryOperation(umath.true_divide, 

1270 _DomainSafeDivide(), 0, 1) 

1271floor_divide = _DomainedBinaryOperation(umath.floor_divide, 

1272 _DomainSafeDivide(), 0, 1) 

1273remainder = _DomainedBinaryOperation(umath.remainder, 

1274 _DomainSafeDivide(), 0, 1) 

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

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

1277 

1278 

1279############################################################################### 

1280# Mask creation functions # 

1281############################################################################### 

1282 

1283 

1284def _replace_dtype_fields_recursive(dtype, primitive_dtype): 

1285 "Private function allowing recursion in _replace_dtype_fields." 

1286 _recurse = _replace_dtype_fields_recursive 

1287 

1288 # Do we have some name fields ? 

1289 if dtype.names is not None: 

1290 descr = [] 

1291 for name in dtype.names: 

1292 field = dtype.fields[name] 

1293 if len(field) == 3: 

1294 # Prepend the title to the name 

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

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

1297 new_dtype = np.dtype(descr) 

1298 

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

1300 elif dtype.subdtype: 

1301 descr = list(dtype.subdtype) 

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

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

1304 

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

1306 else: 

1307 new_dtype = primitive_dtype 

1308 

1309 # preserve identity of dtypes 

1310 if new_dtype == dtype: 

1311 new_dtype = dtype 

1312 

1313 return new_dtype 

1314 

1315 

1316def _replace_dtype_fields(dtype, primitive_dtype): 

1317 """ 

1318 Construct a dtype description list from a given dtype. 

1319 

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

1321 recursively replaced with `primitive_dtype`. 

1322 

1323 Arguments are coerced to dtypes first. 

1324 """ 

1325 dtype = np.dtype(dtype) 

1326 primitive_dtype = np.dtype(primitive_dtype) 

1327 return _replace_dtype_fields_recursive(dtype, primitive_dtype) 

1328 

1329 

1330def make_mask_descr(ndtype): 

1331 """ 

1332 Construct a dtype description list from a given dtype. 

1333 

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

1335 boolean type. Field names are not altered. 

1336 

1337 Parameters 

1338 ---------- 

1339 ndtype : dtype 

1340 The dtype to convert. 

1341 

1342 Returns 

1343 ------- 

1344 result : dtype 

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

1346 

1347 Examples 

1348 -------- 

1349 >>> import numpy.ma as ma 

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

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

1352 >>> dtype 

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

1354 >>> ma.make_mask_descr(dtype) 

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

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

1357 dtype('bool') 

1358 

1359 """ 

1360 return _replace_dtype_fields(ndtype, MaskType) 

1361 

1362 

1363def getmask(a): 

1364 """ 

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

1366 

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

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

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

1370 

1371 Parameters 

1372 ---------- 

1373 a : array_like 

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

1375 

1376 See Also 

1377 -------- 

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

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

1380 

1381 Examples 

1382 -------- 

1383 >>> import numpy.ma as ma 

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

1385 >>> a 

1386 masked_array( 

1387 data=[[1, --], 

1388 [3, 4]], 

1389 mask=[[False, True], 

1390 [False, False]], 

1391 fill_value=2) 

1392 >>> ma.getmask(a) 

1393 array([[False, True], 

1394 [False, False]]) 

1395 

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

1397 

1398 >>> a.mask 

1399 array([[False, True], 

1400 [False, False]]) 

1401 

1402 Result when mask == `nomask` 

1403 

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

1405 >>> b 

1406 masked_array( 

1407 data=[[1, 2], 

1408 [3, 4]], 

1409 mask=False, 

1410 fill_value=999999) 

1411 >>> ma.nomask 

1412 False 

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

1414 True 

1415 >>> b.mask == ma.nomask 

1416 True 

1417 

1418 """ 

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

1420 

1421 

1422get_mask = getmask 

1423 

1424 

1425def getmaskarray(arr): 

1426 """ 

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

1428 

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

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

1431 the same shape as `arr`. 

1432 

1433 Parameters 

1434 ---------- 

1435 arr : array_like 

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

1437 

1438 See Also 

1439 -------- 

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

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

1442 

1443 Examples 

1444 -------- 

1445 >>> import numpy.ma as ma 

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

1447 >>> a 

1448 masked_array( 

1449 data=[[1, --], 

1450 [3, 4]], 

1451 mask=[[False, True], 

1452 [False, False]], 

1453 fill_value=2) 

1454 >>> ma.getmaskarray(a) 

1455 array([[False, True], 

1456 [False, False]]) 

1457 

1458 Result when mask == ``nomask`` 

1459 

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

1461 >>> b 

1462 masked_array( 

1463 data=[[1, 2], 

1464 [3, 4]], 

1465 mask=False, 

1466 fill_value=999999) 

1467 >>> ma.getmaskarray(b) 

1468 array([[False, False], 

1469 [False, False]]) 

1470 

1471 """ 

1472 mask = getmask(arr) 

1473 if mask is nomask: 

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

1475 return mask 

1476 

1477 

1478def is_mask(m): 

1479 """ 

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

1481 

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

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

1484 mask has a flexible dtype. 

1485 

1486 Parameters 

1487 ---------- 

1488 m : array_like 

1489 Array to test. 

1490 

1491 Returns 

1492 ------- 

1493 result : bool 

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

1495 

1496 See Also 

1497 -------- 

1498 isMaskedArray : Test whether input is an instance of MaskedArray. 

1499 

1500 Examples 

1501 -------- 

1502 >>> import numpy.ma as ma 

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

1504 >>> m 

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

1506 mask=[ True, False, True, False, False], 

1507 fill_value=0) 

1508 >>> ma.is_mask(m) 

1509 False 

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

1511 True 

1512 

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

1514 for it to be considered a valid mask. 

1515 

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

1517 >>> ma.is_mask(m) 

1518 False 

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

1520 >>> m 

1521 array([False, True, False]) 

1522 >>> ma.is_mask(m) 

1523 True 

1524 

1525 Arrays with complex dtypes don't return True. 

1526 

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

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

1529 >>> dtype 

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

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

1532 ... dtype=dtype) 

1533 >>> m 

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

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

1536 >>> ma.is_mask(m) 

1537 False 

1538 

1539 """ 

1540 try: 

1541 return m.dtype.type is MaskType 

1542 except AttributeError: 

1543 return False 

1544 

1545 

1546def _shrink_mask(m): 

1547 """ 

1548 Shrink a mask to nomask if possible 

1549 """ 

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

1551 return nomask 

1552 else: 

1553 return m 

1554 

1555 

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

1557 """ 

1558 Create a boolean mask from an array. 

1559 

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

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

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

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

1564 

1565 Parameters 

1566 ---------- 

1567 m : array_like 

1568 Potential mask. 

1569 copy : bool, optional 

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

1571 shrink : bool, optional 

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

1573 dtype : dtype, optional 

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

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

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

1577 case ``nomask`` is always returned. 

1578 

1579 Returns 

1580 ------- 

1581 result : ndarray 

1582 A boolean mask derived from `m`. 

1583 

1584 Examples 

1585 -------- 

1586 >>> import numpy.ma as ma 

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

1588 >>> ma.make_mask(m) 

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

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

1591 >>> ma.make_mask(m) 

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

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

1594 >>> ma.make_mask(m) 

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

1596 

1597 Effect of the `shrink` parameter. 

1598 

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

1600 >>> m 

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

1602 >>> ma.make_mask(m) 

1603 False 

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

1605 array([False, False, False, False]) 

1606 

1607 Using a flexible `dtype`. 

1608 

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

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

1611 >>> arr = [] 

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

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

1614 >>> arr 

1615 [(1, 0), (0, 1), (1, 0), (1, 0)] 

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

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

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

1619 >>> arr 

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

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

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

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

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

1625 

1626 """ 

1627 if m is nomask: 

1628 return nomask 

1629 

1630 # Make sure the input dtype is valid. 

1631 dtype = make_mask_descr(dtype) 

1632 

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

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

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

1636 

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

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

1639 # Bas les masques ! 

1640 if shrink: 

1641 result = _shrink_mask(result) 

1642 return result 

1643 

1644 

1645def make_mask_none(newshape, dtype=None): 

1646 """ 

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

1648 

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

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

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

1652 

1653 Parameters 

1654 ---------- 

1655 newshape : tuple 

1656 A tuple indicating the shape of the mask. 

1657 dtype : {None, dtype}, optional 

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

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

1660 

1661 Returns 

1662 ------- 

1663 result : ndarray 

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

1665 

1666 See Also 

1667 -------- 

1668 make_mask : Create a boolean mask from an array. 

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

1670 

1671 Examples 

1672 -------- 

1673 >>> import numpy.ma as ma 

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

1675 array([False, False, False]) 

1676 

1677 Defining a more complex dtype. 

1678 

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

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

1681 >>> dtype 

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

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

1684 array([(False, False), (False, False), (False, False)], 

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

1686 

1687 """ 

1688 if dtype is None: 

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

1690 else: 

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

1692 return result 

1693 

1694 

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

1696 """ 

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

1698 

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

1700 (i.e. False). 

1701 

1702 Parameters 

1703 ---------- 

1704 m1, m2 : array_like 

1705 Input masks. 

1706 copy : bool, optional 

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

1708 of the other input mask. Defaults to False. 

1709 shrink : bool, optional 

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

1711 False. Defaults to True. 

1712 

1713 Returns 

1714 ------- 

1715 mask : output mask 

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

1717 

1718 Raises 

1719 ------ 

1720 ValueError 

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

1722 

1723 Examples 

1724 -------- 

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

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

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

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

1729 

1730 """ 

1731 

1732 @recursive 

1733 def _recursive_mask_or(self, m1, m2, newmask): 

1734 names = m1.dtype.names 

1735 for name in names: 

1736 current1 = m1[name] 

1737 if current1.dtype.names is not None: 

1738 self(current1, m2[name], newmask[name]) 

1739 else: 

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

1741 return 

1742 

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

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

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

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

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

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

1749 if m1 is m2 and is_mask(m1): 

1750 return m1 

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

1752 if dtype1 != dtype2: 

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

1754 if dtype1.names is not None: 

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

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

1757 _recursive_mask_or(m1, m2, newmask) 

1758 return newmask 

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

1760 

1761 

1762def flatten_mask(mask): 

1763 """ 

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

1765 are collapsed. 

1766 

1767 Parameters 

1768 ---------- 

1769 mask : array_like 

1770 Input array, which will be interpreted as booleans. 

1771 

1772 Returns 

1773 ------- 

1774 flattened_mask : ndarray of bools 

1775 The flattened input. 

1776 

1777 Examples 

1778 -------- 

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

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

1781 array([False, False, True]) 

1782 

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

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

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

1786 

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

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

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

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

1791 

1792 """ 

1793 

1794 def _flatmask(mask): 

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

1796 mnames = mask.dtype.names 

1797 if mnames is not None: 

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

1799 else: 

1800 return mask 

1801 

1802 def _flatsequence(sequence): 

1803 "Generates a flattened version of the sequence." 

1804 try: 

1805 for element in sequence: 

1806 if hasattr(element, '__iter__'): 

1807 yield from _flatsequence(element) 

1808 else: 

1809 yield element 

1810 except TypeError: 

1811 yield sequence 

1812 

1813 mask = np.asarray(mask) 

1814 flattened = _flatsequence(_flatmask(mask)) 

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

1816 

1817 

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

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

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

1821 if mask is not nomask: 

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

1823 return nomask 

1824 

1825 

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

1827# Masking functions # 

1828############################################################################### 

1829 

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

1831 """ 

1832 Mask an array where a condition is met. 

1833 

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

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

1836 

1837 Parameters 

1838 ---------- 

1839 condition : array_like 

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

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

1842 a : array_like 

1843 Array to mask. 

1844 copy : bool 

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

1846 `a` in place and return a view. 

1847 

1848 Returns 

1849 ------- 

1850 result : MaskedArray 

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

1852 

1853 See Also 

1854 -------- 

1855 masked_values : Mask using floating point equality. 

1856 masked_equal : Mask where equal to a given value. 

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

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

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

1860 masked_less : Mask where less than a given value. 

1861 masked_greater : Mask where greater than a given value. 

1862 masked_inside : Mask inside a given interval. 

1863 masked_outside : Mask outside a given interval. 

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

1865 

1866 Examples 

1867 -------- 

1868 >>> import numpy.ma as ma 

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

1870 >>> a 

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

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

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

1874 mask=[ True, True, True, False], 

1875 fill_value=999999) 

1876 

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

1878 

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

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

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

1882 mask=[False, False, True, False], 

1883 fill_value='N/A', 

1884 dtype='<U1') 

1885 

1886 Effect of the `copy` argument. 

1887 

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

1889 >>> c 

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

1891 mask=[ True, True, True, False], 

1892 fill_value=999999) 

1893 >>> c[0] = 99 

1894 >>> c 

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

1896 mask=[False, True, True, False], 

1897 fill_value=999999) 

1898 >>> a 

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

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

1901 >>> c[0] = 99 

1902 >>> c 

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

1904 mask=[False, True, True, False], 

1905 fill_value=999999) 

1906 >>> a 

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

1908 

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

1910 

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

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

1913 >>> a 

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

1915 mask=[False, False, True, False], 

1916 fill_value=999999) 

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

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

1919 >>> b 

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

1921 mask=[ True, False, False, False], 

1922 fill_value=999999) 

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

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

1925 mask=[ True, False, True, True], 

1926 fill_value=999999) 

1927 

1928 """ 

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

1930 cond = make_mask(condition, shrink=False) 

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

1932 

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

1934 if cshape and cshape != ashape: 

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

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

1937 if hasattr(a, '_mask'): 

1938 cond = mask_or(cond, a._mask) 

1939 cls = type(a) 

1940 else: 

1941 cls = MaskedArray 

1942 result = a.view(cls) 

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

1944 result.mask = _shrink_mask(cond) 

1945 return result 

1946 

1947 

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

1949 """ 

1950 Mask an array where greater than a given value. 

1951 

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

1953 `condition` = (x > value). 

1954 

1955 See Also 

1956 -------- 

1957 masked_where : Mask where a condition is met. 

1958 

1959 Examples 

1960 -------- 

1961 >>> import numpy.ma as ma 

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

1963 >>> a 

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

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

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

1967 mask=[False, False, False, True], 

1968 fill_value=999999) 

1969 

1970 """ 

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

1972 

1973 

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

1975 """ 

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

1977 

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

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

1980 

1981 See Also 

1982 -------- 

1983 masked_where : Mask where a condition is met. 

1984 

1985 Examples 

1986 -------- 

1987 >>> import numpy.ma as ma 

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

1989 >>> a 

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

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

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

1993 mask=[False, False, True, True], 

1994 fill_value=999999) 

1995 

1996 """ 

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

1998 

1999 

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

2001 """ 

2002 Mask an array where less than a given value. 

2003 

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

2005 `condition` = (x < value). 

2006 

2007 See Also 

2008 -------- 

2009 masked_where : Mask where a condition is met. 

2010 

2011 Examples 

2012 -------- 

2013 >>> import numpy.ma as ma 

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

2015 >>> a 

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

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

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

2019 mask=[ True, True, False, False], 

2020 fill_value=999999) 

2021 

2022 """ 

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

2024 

2025 

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

2027 """ 

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

2029 

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

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

2032 

2033 See Also 

2034 -------- 

2035 masked_where : Mask where a condition is met. 

2036 

2037 Examples 

2038 -------- 

2039 >>> import numpy.ma as ma 

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

2041 >>> a 

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

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

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

2045 mask=[ True, True, True, False], 

2046 fill_value=999999) 

2047 

2048 """ 

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

2050 

2051 

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

2053 """ 

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

2055 

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

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

2058 

2059 See Also 

2060 -------- 

2061 masked_where : Mask where a condition is met. 

2062 

2063 Examples 

2064 -------- 

2065 >>> import numpy.ma as ma 

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

2067 >>> a 

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

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

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

2071 mask=[ True, True, False, True], 

2072 fill_value=999999) 

2073 

2074 """ 

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

2076 

2077 

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

2079 """ 

2080 Mask an array where equal to a given value. 

2081 

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

2083 `condition` = (x == value). For floating point arrays, 

2084 consider using ``masked_values(x, value)``. 

2085 

2086 See Also 

2087 -------- 

2088 masked_where : Mask where a condition is met. 

2089 masked_values : Mask using floating point equality. 

2090 

2091 Examples 

2092 -------- 

2093 >>> import numpy.ma as ma 

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

2095 >>> a 

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

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

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

2099 mask=[False, False, True, False], 

2100 fill_value=2) 

2101 

2102 """ 

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

2104 output.fill_value = value 

2105 return output 

2106 

2107 

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

2109 """ 

2110 Mask an array inside a given interval. 

2111 

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

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

2114 can be given in either order. 

2115 

2116 See Also 

2117 -------- 

2118 masked_where : Mask where a condition is met. 

2119 

2120 Notes 

2121 ----- 

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

2123 

2124 Examples 

2125 -------- 

2126 >>> import numpy.ma as ma 

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

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

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

2130 mask=[False, False, True, True, False, False], 

2131 fill_value=1e+20) 

2132 

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

2134 

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

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

2137 mask=[False, False, True, True, False, False], 

2138 fill_value=1e+20) 

2139 

2140 """ 

2141 if v2 < v1: 

2142 (v1, v2) = (v2, v1) 

2143 xf = filled(x) 

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

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

2146 

2147 

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

2149 """ 

2150 Mask an array outside a given interval. 

2151 

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

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

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

2155 

2156 See Also 

2157 -------- 

2158 masked_where : Mask where a condition is met. 

2159 

2160 Notes 

2161 ----- 

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

2163 

2164 Examples 

2165 -------- 

2166 >>> import numpy.ma as ma 

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

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

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

2170 mask=[ True, True, False, False, True, True], 

2171 fill_value=1e+20) 

2172 

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

2174 

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

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

2177 mask=[ True, True, False, False, True, True], 

2178 fill_value=1e+20) 

2179 

2180 """ 

2181 if v2 < v1: 

2182 (v1, v2) = (v2, v1) 

2183 xf = filled(x) 

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

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

2186 

2187 

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

2189 """ 

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

2191 

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

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

2194 

2195 Parameters 

2196 ---------- 

2197 x : array_like 

2198 Array to mask 

2199 value : object 

2200 Comparison value 

2201 copy : {True, False}, optional 

2202 Whether to return a copy of `x`. 

2203 shrink : {True, False}, optional 

2204 Whether to collapse a mask full of False to nomask 

2205 

2206 Returns 

2207 ------- 

2208 result : MaskedArray 

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

2210 

2211 See Also 

2212 -------- 

2213 masked_where : Mask where a condition is met. 

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

2215 masked_values : Mask using floating point equality. 

2216 

2217 Examples 

2218 -------- 

2219 >>> import numpy.ma as ma 

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

2221 >>> # don't eat spoiled food 

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

2223 >>> eat 

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

2225 mask=[ True, False], 

2226 fill_value='green_eggs', 

2227 dtype=object) 

2228 >>> # plain ol` ham is boring 

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

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

2231 >>> eat 

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

2233 mask=False, 

2234 fill_value='green_eggs', 

2235 dtype=object) 

2236 

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

2238 

2239 >>> eat 

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

2241 mask=False, 

2242 fill_value='green_eggs', 

2243 dtype=object) 

2244 

2245 """ 

2246 if isMaskedArray(x): 

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

2248 mask = x._mask 

2249 else: 

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

2251 mask = nomask 

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

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

2254 

2255 

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

2257 """ 

2258 Mask using floating point equality. 

2259 

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

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

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

2263 

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

2265 `masked_equal`. 

2266 

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

2268 possible. 

2269 

2270 Parameters 

2271 ---------- 

2272 x : array_like 

2273 Array to mask. 

2274 value : float 

2275 Masking value. 

2276 rtol, atol : float, optional 

2277 Tolerance parameters passed on to `isclose` 

2278 copy : bool, optional 

2279 Whether to return a copy of `x`. 

2280 shrink : bool, optional 

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

2282 

2283 Returns 

2284 ------- 

2285 result : MaskedArray 

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

2287 

2288 See Also 

2289 -------- 

2290 masked_where : Mask where a condition is met. 

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

2292 

2293 Examples 

2294 -------- 

2295 >>> import numpy.ma as ma 

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

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

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

2299 mask=[False, True, False, True, False], 

2300 fill_value=1.1) 

2301 

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

2303 

2304 >>> ma.masked_values(x, 1.5) 

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

2306 mask=False, 

2307 fill_value=1.5) 

2308 

2309 For integers, the fill value will be different in general to the 

2310 result of ``masked_equal``. 

2311 

2312 >>> x = np.arange(5) 

2313 >>> x 

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

2315 >>> ma.masked_values(x, 2) 

2316 masked_array(data=[0, 1, --, 3, 4], 

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

2318 fill_value=2) 

2319 >>> ma.masked_equal(x, 2) 

2320 masked_array(data=[0, 1, --, 3, 4], 

2321 mask=[False, False, True, False, False], 

2322 fill_value=2) 

2323 

2324 """ 

2325 xnew = filled(x, value) 

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

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

2328 else: 

2329 mask = umath.equal(xnew, value) 

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

2331 if shrink: 

2332 ret.shrink_mask() 

2333 return ret 

2334 

2335 

2336def masked_invalid(a, copy=True): 

2337 """ 

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

2339 

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

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

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

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

2344 

2345 See Also 

2346 -------- 

2347 masked_where : Mask where a condition is met. 

2348 

2349 Examples 

2350 -------- 

2351 >>> import numpy.ma as ma 

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

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

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

2355 >>> a 

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

2357 >>> ma.masked_invalid(a) 

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

2359 mask=[False, False, True, True, False], 

2360 fill_value=1e+20) 

2361 

2362 """ 

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

2364 mask = getattr(a, '_mask', None) 

2365 if mask is not None: 

2366 condition = ~(np.isfinite(getdata(a))) 

2367 if mask is not nomask: 

2368 condition |= mask 

2369 cls = type(a) 

2370 else: 

2371 condition = ~(np.isfinite(a)) 

2372 cls = MaskedArray 

2373 result = a.view(cls) 

2374 result._mask = condition 

2375 return result 

2376 

2377 

2378############################################################################### 

2379# Printing options # 

2380############################################################################### 

2381 

2382 

2383class _MaskedPrintOption: 

2384 """ 

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

2386 

2387 """ 

2388 

2389 def __init__(self, display): 

2390 """ 

2391 Create the masked_print_option object. 

2392 

2393 """ 

2394 self._display = display 

2395 self._enabled = True 

2396 

2397 def display(self): 

2398 """ 

2399 Display the string to print for masked values. 

2400 

2401 """ 

2402 return self._display 

2403 

2404 def set_display(self, s): 

2405 """ 

2406 Set the string to print for masked values. 

2407 

2408 """ 

2409 self._display = s 

2410 

2411 def enabled(self): 

2412 """ 

2413 Is the use of the display value enabled? 

2414 

2415 """ 

2416 return self._enabled 

2417 

2418 def enable(self, shrink=1): 

2419 """ 

2420 Set the enabling shrink to `shrink`. 

2421 

2422 """ 

2423 self._enabled = shrink 

2424 

2425 def __str__(self): 

2426 return str(self._display) 

2427 

2428 __repr__ = __str__ 

2429 

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

2431masked_print_option = _MaskedPrintOption('--') 

2432 

2433 

2434def _recursive_printoption(result, mask, printopt): 

2435 """ 

2436 Puts printoptions in result where mask is True. 

2437 

2438 Private function allowing for recursion 

2439 

2440 """ 

2441 names = result.dtype.names 

2442 if names is not None: 

2443 for name in names: 

2444 curdata = result[name] 

2445 curmask = mask[name] 

2446 _recursive_printoption(curdata, curmask, printopt) 

2447 else: 

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

2449 return 

2450 

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

2452_legacy_print_templates = dict( 

2453 long_std=textwrap.dedent("""\ 

2454 masked_%(name)s(data = 

2455 %(data)s, 

2456 %(nlen)s mask = 

2457 %(mask)s, 

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

2459 """), 

2460 long_flx=textwrap.dedent("""\ 

2461 masked_%(name)s(data = 

2462 %(data)s, 

2463 %(nlen)s mask = 

2464 %(mask)s, 

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

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

2467 """), 

2468 short_std=textwrap.dedent("""\ 

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

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

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

2472 """), 

2473 short_flx=textwrap.dedent("""\ 

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

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

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

2477 %(nlen)s dtype = %(dtype)s) 

2478 """) 

2479) 

2480 

2481############################################################################### 

2482# MaskedArray class # 

2483############################################################################### 

2484 

2485 

2486def _recursive_filled(a, mask, fill_value): 

2487 """ 

2488 Recursively fill `a` with `fill_value`. 

2489 

2490 """ 

2491 names = a.dtype.names 

2492 for name in names: 

2493 current = a[name] 

2494 if current.dtype.names is not None: 

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

2496 else: 

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

2498 

2499 

2500def flatten_structured_array(a): 

2501 """ 

2502 Flatten a structured array. 

2503 

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

2505 (nested) fields. 

2506 

2507 Parameters 

2508 ---------- 

2509 a : structured array 

2510 

2511 Returns 

2512 ------- 

2513 output : masked array or ndarray 

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

2515 standard ndarray. 

2516 

2517 Examples 

2518 -------- 

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

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

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

2522 array([[1., 1.], 

2523 [2., 2.]]) 

2524 

2525 """ 

2526 

2527 def flatten_sequence(iterable): 

2528 """ 

2529 Flattens a compound of nested iterables. 

2530 

2531 """ 

2532 for elm in iter(iterable): 

2533 if hasattr(elm, '__iter__'): 

2534 yield from flatten_sequence(elm) 

2535 else: 

2536 yield elm 

2537 

2538 a = np.asanyarray(a) 

2539 inishape = a.shape 

2540 a = a.ravel() 

2541 if isinstance(a, MaskedArray): 

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

2543 out = out.view(MaskedArray) 

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

2545 for d in getmaskarray(a)]) 

2546 else: 

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

2548 if len(inishape) > 1: 

2549 newshape = list(out.shape) 

2550 newshape[0] = inishape 

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

2552 return out 

2553 

2554 

2555def _arraymethod(funcname, onmask=True): 

2556 """ 

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

2558 

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

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

2561 on the original ``_data``. 

2562 

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

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

2565 to the initial mask. 

2566 

2567 Parameters 

2568 ---------- 

2569 funcname : str 

2570 Name of the function to apply on data. 

2571 onmask : bool 

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

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

2574 attribute. 

2575 

2576 Returns 

2577 ------- 

2578 method : instancemethod 

2579 Class method wrapper of the specified basic array method. 

2580 

2581 """ 

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

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

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

2585 result._update_from(self) 

2586 mask = self._mask 

2587 if not onmask: 

2588 result.__setmask__(mask) 

2589 elif mask is not nomask: 

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

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

2592 return result 

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

2594 if methdoc is not None: 

2595 wrapped_method.__doc__ = methdoc.__doc__ 

2596 wrapped_method.__name__ = funcname 

2597 return wrapped_method 

2598 

2599 

2600class MaskedIterator: 

2601 """ 

2602 Flat iterator object to iterate over masked arrays. 

2603 

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

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

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

2607 

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

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

2610 advanced indexing. 

2611 

2612 See Also 

2613 -------- 

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

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

2616 

2617 Notes 

2618 ----- 

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

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

2621 

2622 Examples 

2623 -------- 

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

2625 >>> fl = x.flat 

2626 >>> type(fl) 

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

2628 >>> for item in fl: 

2629 ... print(item) 

2630 ... 

2631 0 

2632 1 

2633 2 

2634 3 

2635 4 

2636 5 

2637 

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

2639 returns a masked array: 

2640 

2641 >>> fl[2:4] 

2642 masked_array(data = [2 3], 

2643 mask = False, 

2644 fill_value = 999999) 

2645 

2646 """ 

2647 

2648 def __init__(self, ma): 

2649 self.ma = ma 

2650 self.dataiter = ma._data.flat 

2651 

2652 if ma._mask is nomask: 

2653 self.maskiter = None 

2654 else: 

2655 self.maskiter = ma._mask.flat 

2656 

2657 def __iter__(self): 

2658 return self 

2659 

2660 def __getitem__(self, indx): 

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

2662 if self.maskiter is not None: 

2663 _mask = self.maskiter.__getitem__(indx) 

2664 if isinstance(_mask, ndarray): 

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

2666 _mask.shape = result.shape 

2667 result._mask = _mask 

2668 elif isinstance(_mask, np.void): 

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

2670 elif _mask: # Just a scalar, masked 

2671 return masked 

2672 return result 

2673 

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

2675 def __setitem__(self, index, value): 

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

2677 if self.maskiter is not None: 

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

2679 

2680 def __next__(self): 

2681 """ 

2682 Return the next value, or raise StopIteration. 

2683 

2684 Examples 

2685 -------- 

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

2687 >>> fl = x.flat 

2688 >>> next(fl) 

2689 3 

2690 >>> next(fl) 

2691 masked 

2692 >>> next(fl) 

2693 Traceback (most recent call last): 

2694 ... 

2695 StopIteration 

2696 

2697 """ 

2698 d = next(self.dataiter) 

2699 if self.maskiter is not None: 

2700 m = next(self.maskiter) 

2701 if isinstance(m, np.void): 

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

2703 elif m: # Just a scalar, masked 

2704 return masked 

2705 return d 

2706 

2707 

2708class MaskedArray(ndarray): 

2709 """ 

2710 An array class with possibly masked values. 

2711 

2712 Masked values of True exclude the corresponding element from any 

2713 computation. 

2714 

2715 Construction:: 

2716 

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

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

2719 shrink=True, order=None) 

2720 

2721 Parameters 

2722 ---------- 

2723 data : array_like 

2724 Input data. 

2725 mask : sequence, optional 

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

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

2728 dtype : dtype, optional 

2729 Data type of the output. 

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

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

2732 a copy is performed. 

2733 copy : bool, optional 

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

2735 Default is False. 

2736 subok : bool, optional 

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

2738 plain `MaskedArray`. Default is True. 

2739 ndmin : int, optional 

2740 Minimum number of dimensions. Default is 0. 

2741 fill_value : scalar, optional 

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

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

2744 keep_mask : bool, optional 

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

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

2747 hard_mask : bool, optional 

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

2749 cannot be unmasked. Default is False. 

2750 shrink : bool, optional 

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

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

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

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

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

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

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

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

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

2760 

2761 Examples 

2762 -------- 

2763 

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

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

2766 

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

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

2769 ... [False, False, True]]) 

2770 masked_array( 

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

2772 [3, 4, --]], 

2773 mask=[[False, True, False], 

2774 [False, False, True]], 

2775 fill_value=999999) 

2776 

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

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

2779 boolean value: 

2780 

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

2782 masked_array( 

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

2784 [3, 4, 5]], 

2785 mask=[[False, False, False], 

2786 [False, False, False]], 

2787 fill_value=999999) 

2788 

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

2790 masked_array( 

2791 data=[[--, --, --], 

2792 [--, --, --]], 

2793 mask=[[ True, True, True], 

2794 [ True, True, True]], 

2795 fill_value=999999, 

2796 dtype=int64) 

2797 

2798 .. note:: 

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

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

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

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

2803 

2804 >>> np.False_ is np.ma.nomask 

2805 True 

2806 

2807 """ 

2808 

2809 __array_priority__ = 15 

2810 _defaultmask = nomask 

2811 _defaulthardmask = False 

2812 _baseclass = ndarray 

2813 

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

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

2816 _print_width = 100 

2817 _print_width_1d = 1500 

2818 

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

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

2821 hard_mask=None, shrink=True, order=None, **options): 

2822 """ 

2823 Create a new masked array from scratch. 

2824 

2825 Notes 

2826 ----- 

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

2828 

2829 """ 

2830 # Process data. 

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

2832 order=order, subok=True, ndmin=ndmin) 

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

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

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

2836 copy = True 

2837 

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

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

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

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

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

2843 else: 

2844 _data = ndarray.view(_data, cls) 

2845 # Backwards compatibility w/ numpy.core.ma. 

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

2847 _data._mask = data._mask 

2848 # FIXME _sharedmask is never used. 

2849 _sharedmask = True 

2850 # Process mask. 

2851 # Type of the mask 

2852 mdtype = make_mask_descr(_data.dtype) 

2853 

2854 if mask is nomask: 

2855 # Case 1. : no mask in input. 

2856 # Erase the current mask ? 

2857 if not keep_mask: 

2858 # With a reduced version 

2859 if shrink: 

2860 _data._mask = nomask 

2861 # With full version 

2862 else: 

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

2864 # Check whether we missed something 

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

2866 try: 

2867 # If data is a sequence of masked array 

2868 mask = np.array([getmaskarray(np.asanyarray(m, dtype=mdtype)) 

2869 for m in data], dtype=mdtype) 

2870 except ValueError: 

2871 # If data is nested 

2872 mask = nomask 

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

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

2875 _data._mask = mask 

2876 _data._sharedmask = False 

2877 else: 

2878 _data._sharedmask = not copy 

2879 if copy: 

2880 _data._mask = _data._mask.copy() 

2881 # Reset the shape of the original mask 

2882 if getmask(data) is not nomask: 

2883 data._mask.shape = data.shape 

2884 else: 

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

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

2887 if mask is True and mdtype == MaskType: 

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

2889 elif mask is False and mdtype == MaskType: 

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

2891 else: 

2892 # Read the mask with the current mdtype 

2893 try: 

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

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

2896 except TypeError: 

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

2898 dtype=mdtype) 

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

2900 if mask.shape != _data.shape: 

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

2902 if nm == 1: 

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

2904 elif nm == nd: 

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

2906 else: 

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

2908 "mask size is %i." 

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

2910 copy = True 

2911 # Set the mask to the new value 

2912 if _data._mask is nomask: 

2913 _data._mask = mask 

2914 _data._sharedmask = not copy 

2915 else: 

2916 if not keep_mask: 

2917 _data._mask = mask 

2918 _data._sharedmask = not copy 

2919 else: 

2920 if _data.dtype.names is not None: 

2921 def _recursive_or(a, b): 

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

2923 for name in a.dtype.names: 

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

2925 if af.dtype.names is not None: 

2926 _recursive_or(af, bf) 

2927 else: 

2928 af |= bf 

2929 

2930 _recursive_or(_data._mask, mask) 

2931 else: 

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

2933 _data._sharedmask = False 

2934 # Update fill_value. 

2935 if fill_value is None: 

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

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

2938 if fill_value is not None: 

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

2940 # Process extra options .. 

2941 if hard_mask is None: 

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

2943 else: 

2944 _data._hardmask = hard_mask 

2945 _data._baseclass = _baseclass 

2946 return _data 

2947 

2948 

2949 def _update_from(self, obj): 

2950 """ 

2951 Copies some attributes of obj to self. 

2952 

2953 """ 

2954 if isinstance(obj, ndarray): 

2955 _baseclass = type(obj) 

2956 else: 

2957 _baseclass = ndarray 

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

2959 _optinfo = {} 

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

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

2962 if not isinstance(obj, MaskedArray): 

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

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

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

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

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

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

2969 _optinfo=_optinfo, 

2970 _basedict=_optinfo) 

2971 self.__dict__.update(_dict) 

2972 self.__dict__.update(_optinfo) 

2973 return 

2974 

2975 def __array_finalize__(self, obj): 

2976 """ 

2977 Finalizes the masked array. 

2978 

2979 """ 

2980 # Get main attributes. 

2981 self._update_from(obj) 

2982 

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2997 # matches the input mask. 

2998 # 

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

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

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

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

3003 # 

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

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

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

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

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

3009 if isinstance(obj, ndarray): 

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

3011 # instead? 

3012 if obj.dtype.names is not None: 

3013 _mask = getmaskarray(obj) 

3014 else: 

3015 _mask = getmask(obj) 

3016 

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

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

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

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

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

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

3023 # side-effecting 'obj' as well. 

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

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

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

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

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

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

3030 # needed and use astype instead of copy. 

3031 if self.dtype == obj.dtype: 

3032 _mask_dtype = _mask.dtype 

3033 else: 

3034 _mask_dtype = make_mask_descr(self.dtype) 

3035 

3036 if self.flags.c_contiguous: 

3037 order = "C" 

3038 elif self.flags.f_contiguous: 

3039 order = "F" 

3040 else: 

3041 order = "K" 

3042 

3043 _mask = _mask.astype(_mask_dtype, order) 

3044 else: 

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

3046 _mask = _mask.view() 

3047 else: 

3048 _mask = nomask 

3049 

3050 self._mask = _mask 

3051 # Finalize the mask 

3052 if self._mask is not nomask: 

3053 try: 

3054 self._mask.shape = self.shape 

3055 except ValueError: 

3056 self._mask = nomask 

3057 except (TypeError, AttributeError): 

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

3059 pass 

3060 

3061 # Finalize the fill_value 

3062 if self._fill_value is not None: 

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

3064 elif self.dtype.names is not None: 

3065 # Finalize the default fill_value for structured arrays 

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

3067 

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

3069 """ 

3070 Special hook for ufuncs. 

3071 

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

3073 

3074 """ 

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

3076 result = obj 

3077 else: 

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

3079 result._update_from(self) 

3080 

3081 if context is not None: 

3082 result._mask = result._mask.copy() 

3083 func, args, out_i = context 

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

3085 input_args = args[:func.nin] 

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

3087 # Get the domain mask 

3088 domain = ufunc_domain.get(func, None) 

3089 if domain is not None: 

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

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

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

3093 

3094 if d.any(): 

3095 # Fill the result where the domain is wrong 

3096 try: 

3097 # Binary domain: take the last value 

3098 fill_value = ufunc_fills[func][-1] 

3099 except TypeError: 

3100 # Unary domain: just use this one 

3101 fill_value = ufunc_fills[func] 

3102 except KeyError: 

3103 # Domain not recognized, use fill_value instead 

3104 fill_value = self.fill_value 

3105 

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

3107 

3108 # Update the mask 

3109 if m is nomask: 

3110 m = d 

3111 else: 

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

3113 m = (m | d) 

3114 

3115 # Make sure the mask has the proper size 

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

3117 return masked 

3118 else: 

3119 result._mask = m 

3120 result._sharedmask = False 

3121 

3122 return result 

3123 

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

3125 """ 

3126 Return a view of the MaskedArray data. 

3127 

3128 Parameters 

3129 ---------- 

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

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

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

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

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

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

3136 parameter). 

3137 type : Python type, optional 

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

3139 default None results in type preservation. 

3140 fill_value : scalar, optional 

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

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

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

3144 

3145 See Also 

3146 -------- 

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

3148 

3149 Notes 

3150 ----- 

3151 

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

3153 

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

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

3156 reinterpretation of the bytes of memory. 

3157 

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

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

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

3161 memory. 

3162 

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

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

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

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

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

3168 value is set to the specified value. 

3169 

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

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

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

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

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

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

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

3177 results. 

3178 """ 

3179 

3180 if dtype is None: 

3181 if type is None: 

3182 output = ndarray.view(self) 

3183 else: 

3184 output = ndarray.view(self, type) 

3185 elif type is None: 

3186 try: 

3187 if issubclass(dtype, ndarray): 

3188 output = ndarray.view(self, dtype) 

3189 dtype = None 

3190 else: 

3191 output = ndarray.view(self, dtype) 

3192 except TypeError: 

3193 output = ndarray.view(self, dtype) 

3194 else: 

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

3196 

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

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

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

3200 if getmask(output) is not nomask: 

3201 output._mask = output._mask.view() 

3202 

3203 # Make sure to reset the _fill_value if needed 

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

3205 if fill_value is None: 

3206 if dtype is None: 

3207 pass # leave _fill_value as is 

3208 else: 

3209 output._fill_value = None 

3210 else: 

3211 output.fill_value = fill_value 

3212 return output 

3213 

3214 def __getitem__(self, indx): 

3215 """ 

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

3217 

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

3219 

3220 """ 

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

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

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

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

3225 dout = self.data[indx] 

3226 _mask = self._mask 

3227 

3228 def _is_scalar(m): 

3229 return not isinstance(m, np.ndarray) 

3230 

3231 def _scalar_heuristic(arr, elem): 

3232 """ 

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

3234 if undecidable without promoting nomask to a full mask 

3235 """ 

3236 # obviously a scalar 

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

3238 return True 

3239 

3240 # object array scalar indexing can return anything 

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

3242 if arr.dtype is not elem.dtype: 

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

3244 # an element 

3245 return True 

3246 

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

3248 # expected - this is not a scalar 

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

3250 return False 

3251 

3252 return None 

3253 

3254 if _mask is not nomask: 

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

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

3257 mout = _mask[indx] 

3258 scalar_expected = _is_scalar(mout) 

3259 

3260 else: 

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

3262 mout = nomask 

3263 scalar_expected = _scalar_heuristic(self.data, dout) 

3264 if scalar_expected is None: 

3265 # heuristics have failed 

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

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

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

3269 

3270 # Did we extract a single item? 

3271 if scalar_expected: 

3272 # A record 

3273 if isinstance(dout, np.void): 

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

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

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

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

3278 

3279 # special case introduced in gh-5962 

3280 elif (self.dtype.type is np.object_ and 

3281 isinstance(dout, np.ndarray) and 

3282 dout is not masked): 

3283 # If masked, turn into a MaskedArray, with everything masked. 

3284 if mout: 

3285 return MaskedArray(dout, mask=True) 

3286 else: 

3287 return dout 

3288 

3289 # Just a scalar 

3290 else: 

3291 if mout: 

3292 return masked 

3293 else: 

3294 return dout 

3295 else: 

3296 # Force dout to MA 

3297 dout = dout.view(type(self)) 

3298 # Inherit attributes from self 

3299 dout._update_from(self) 

3300 # Check the fill_value 

3301 if is_string_or_list_of_strings(indx): 

3302 if self._fill_value is not None: 

3303 dout._fill_value = self._fill_value[indx] 

3304 

3305 # Something like gh-15895 has happened if this check fails. 

3306 # _fill_value should always be an ndarray. 

3307 if not isinstance(dout._fill_value, np.ndarray): 

3308 raise RuntimeError('Internal NumPy error.') 

3309 # If we're indexing a multidimensional field in a 

3310 # structured array (such as dtype("(2,)i2,(2,)i1")), 

3311 # dimensionality goes up (M[field].ndim == M.ndim + 

3312 # M.dtype[field].ndim). That's fine for 

3313 # M[field] but problematic for M[field].fill_value 

3314 # which should have shape () to avoid breaking several 

3315 # methods. There is no great way out, so set to 

3316 # first element. See issue #6723. 

3317 if dout._fill_value.ndim > 0: 

3318 if not (dout._fill_value == 

3319 dout._fill_value.flat[0]).all(): 

3320 warnings.warn( 

3321 "Upon accessing multidimensional field " 

3322 f"{indx!s}, need to keep dimensionality " 

3323 "of fill_value at 0. Discarding " 

3324 "heterogeneous fill_value and setting " 

3325 f"all to {dout._fill_value[0]!s}.", 

3326 stacklevel=2) 

3327 # Need to use `.flat[0:1].squeeze(...)` instead of just 

3328 # `.flat[0]` to ensure the result is a 0d array and not 

3329 # a scalar. 

3330 dout._fill_value = dout._fill_value.flat[0:1].squeeze(axis=0) 

3331 dout._isfield = True 

3332 # Update the mask if needed 

3333 if mout is not nomask: 

3334 # set shape to match that of data; this is needed for matrices 

3335 dout._mask = reshape(mout, dout.shape) 

3336 dout._sharedmask = True 

3337 # Note: Don't try to check for m.any(), that'll take too long 

3338 return dout 

3339 

3340 def __setitem__(self, indx, value): 

3341 """ 

3342 x.__setitem__(i, y) <==> x[i]=y 

3343 

3344 Set item described by index. If value is masked, masks those 

3345 locations. 

3346 

3347 """ 

3348 if self is masked: 

3349 raise MaskError('Cannot alter the masked element.') 

3350 _data = self._data 

3351 _mask = self._mask 

3352 if isinstance(indx, str): 

3353 _data[indx] = value 

3354 if _mask is nomask: 

3355 self._mask = _mask = make_mask_none(self.shape, self.dtype) 

3356 _mask[indx] = getmask(value) 

3357 return 

3358 

3359 _dtype = _data.dtype 

3360 

3361 if value is masked: 

3362 # The mask wasn't set: create a full version. 

3363 if _mask is nomask: 

3364 _mask = self._mask = make_mask_none(self.shape, _dtype) 

3365 # Now, set the mask to its value. 

3366 if _dtype.names is not None: 

3367 _mask[indx] = tuple([True] * len(_dtype.names)) 

3368 else: 

3369 _mask[indx] = True 

3370 return 

3371 

3372 # Get the _data part of the new value 

3373 dval = getattr(value, '_data', value) 

3374 # Get the _mask part of the new value 

3375 mval = getmask(value) 

3376 if _dtype.names is not None and mval is nomask: 

3377 mval = tuple([False] * len(_dtype.names)) 

3378 if _mask is nomask: 

3379 # Set the data, then the mask 

3380 _data[indx] = dval 

3381 if mval is not nomask: 

3382 _mask = self._mask = make_mask_none(self.shape, _dtype) 

3383 _mask[indx] = mval 

3384 elif not self._hardmask: 

3385 # Set the data, then the mask 

3386 _data[indx] = dval 

3387 _mask[indx] = mval 

3388 elif hasattr(indx, 'dtype') and (indx.dtype == MaskType): 

3389 indx = indx * umath.logical_not(_mask) 

3390 _data[indx] = dval 

3391 else: 

3392 if _dtype.names is not None: 

3393 err_msg = "Flexible 'hard' masks are not yet supported." 

3394 raise NotImplementedError(err_msg) 

3395 mindx = mask_or(_mask[indx], mval, copy=True) 

3396 dindx = self._data[indx] 

3397 if dindx.size > 1: 

3398 np.copyto(dindx, dval, where=~mindx) 

3399 elif mindx is nomask: 

3400 dindx = dval 

3401 _data[indx] = dindx 

3402 _mask[indx] = mindx 

3403 return 

3404 

3405 # Define so that we can overwrite the setter. 

3406 @property 

3407 def dtype(self): 

3408 return super(MaskedArray, self).dtype 

3409 

3410 @dtype.setter 

3411 def dtype(self, dtype): 

3412 super(MaskedArray, type(self)).dtype.__set__(self, dtype) 

3413 if self._mask is not nomask: 

3414 self._mask = self._mask.view(make_mask_descr(dtype), ndarray) 

3415 # Try to reset the shape of the mask (if we don't have a void). 

3416 # This raises a ValueError if the dtype change won't work. 

3417 try: 

3418 self._mask.shape = self.shape 

3419 except (AttributeError, TypeError): 

3420 pass 

3421 

3422 @property 

3423 def shape(self): 

3424 return super(MaskedArray, self).shape 

3425 

3426 @shape.setter 

3427 def shape(self, shape): 

3428 super(MaskedArray, type(self)).shape.__set__(self, shape) 

3429 # Cannot use self._mask, since it may not (yet) exist when a 

3430 # masked matrix sets the shape. 

3431 if getmask(self) is not nomask: 

3432 self._mask.shape = self.shape 

3433 

3434 def __setmask__(self, mask, copy=False): 

3435 """ 

3436 Set the mask. 

3437 

3438 """ 

3439 idtype = self.dtype 

3440 current_mask = self._mask 

3441 if mask is masked: 

3442 mask = True 

3443 

3444 if current_mask is nomask: 

3445 # Make sure the mask is set 

3446 # Just don't do anything if there's nothing to do. 

3447 if mask is nomask: 

3448 return 

3449 current_mask = self._mask = make_mask_none(self.shape, idtype) 

3450 

3451 if idtype.names is None: 

3452 # No named fields. 

3453 # Hardmask: don't unmask the data 

3454 if self._hardmask: 

3455 current_mask |= mask 

3456 # Softmask: set everything to False 

3457 # If it's obviously a compatible scalar, use a quick update 

3458 # method. 

3459 elif isinstance(mask, (int, float, np.bool_, np.number)): 

3460 current_mask[...] = mask 

3461 # Otherwise fall back to the slower, general purpose way. 

3462 else: 

3463 current_mask.flat = mask 

3464 else: 

3465 # Named fields w/ 

3466 mdtype = current_mask.dtype 

3467 mask = np.array(mask, copy=False) 

3468 # Mask is a singleton 

3469 if not mask.ndim: 

3470 # It's a boolean : make a record 

3471 if mask.dtype.kind == 'b': 

3472 mask = np.array(tuple([mask.item()] * len(mdtype)), 

3473 dtype=mdtype) 

3474 # It's a record: make sure the dtype is correct 

3475 else: 

3476 mask = mask.astype(mdtype) 

3477 # Mask is a sequence 

3478 else: 

3479 # Make sure the new mask is a ndarray with the proper dtype 

3480 try: 

3481 mask = np.array(mask, copy=copy, dtype=mdtype) 

3482 # Or assume it's a sequence of bool/int 

3483 except TypeError: 

3484 mask = np.array([tuple([m] * len(mdtype)) for m in mask], 

3485 dtype=mdtype) 

3486 # Hardmask: don't unmask the data 

3487 if self._hardmask: 

3488 for n in idtype.names: 

3489 current_mask[n] |= mask[n] 

3490 # Softmask: set everything to False 

3491 # If it's obviously a compatible scalar, use a quick update 

3492 # method. 

3493 elif isinstance(mask, (int, float, np.bool_, np.number)): 

3494 current_mask[...] = mask 

3495 # Otherwise fall back to the slower, general purpose way. 

3496 else: 

3497 current_mask.flat = mask 

3498 # Reshape if needed 

3499 if current_mask.shape: 

3500 current_mask.shape = self.shape 

3501 return 

3502 

3503 _set_mask = __setmask__ 

3504 

3505 @property 

3506 def mask(self): 

3507 """ Current mask. """ 

3508 

3509 # We could try to force a reshape, but that wouldn't work in some 

3510 # cases. 

3511 # Return a view so that the dtype and shape cannot be changed in place 

3512 # This still preserves nomask by identity 

3513 return self._mask.view() 

3514 

3515 @mask.setter 

3516 def mask(self, value): 

3517 self.__setmask__(value) 

3518 

3519 @property 

3520 def recordmask(self): 

3521 """ 

3522 Get or set the mask of the array if it has no named fields. For 

3523 structured arrays, returns a ndarray of booleans where entries are 

3524 ``True`` if **all** the fields are masked, ``False`` otherwise: 

3525 

3526 >>> x = np.ma.array([(1, 1), (2, 2), (3, 3), (4, 4), (5, 5)], 

3527 ... mask=[(0, 0), (1, 0), (1, 1), (0, 1), (0, 0)], 

3528 ... dtype=[('a', int), ('b', int)]) 

3529 >>> x.recordmask 

3530 array([False, False, True, False, False]) 

3531 """ 

3532 

3533 _mask = self._mask.view(ndarray) 

3534 if _mask.dtype.names is None: 

3535 return _mask 

3536 return np.all(flatten_structured_array(_mask), axis=-1) 

3537 

3538 @recordmask.setter 

3539 def recordmask(self, mask): 

3540 raise NotImplementedError("Coming soon: setting the mask per records!") 

3541 

3542 def harden_mask(self): 

3543 """ 

3544 Force the mask to hard. 

3545 

3546 Whether the mask of a masked array is hard or soft is determined by 

3547 its `hardmask` property. `harden_mask` sets `hardmask` to True. 

3548 

3549 See Also 

3550 -------- 

3551 hardmask 

3552 

3553 """ 

3554 self._hardmask = True 

3555 return self 

3556 

3557 def soften_mask(self): 

3558 """ 

3559 Force the mask to soft. 

3560 

3561 Whether the mask of a masked array is hard or soft is determined by 

3562 its `hardmask` property. `soften_mask` sets `hardmask` to False. 

3563 

3564 See Also 

3565 -------- 

3566 hardmask 

3567 

3568 """ 

3569 self._hardmask = False 

3570 return self 

3571 

3572 @property 

3573 def hardmask(self): 

3574 """ Hardness of the mask """ 

3575 return self._hardmask 

3576 

3577 def unshare_mask(self): 

3578 """ 

3579 Copy the mask and set the sharedmask flag to False. 

3580 

3581 Whether the mask is shared between masked arrays can be seen from 

3582 the `sharedmask` property. `unshare_mask` ensures the mask is not shared. 

3583 A copy of the mask is only made if it was shared. 

3584 

3585 See Also 

3586 -------- 

3587 sharedmask 

3588 

3589 """ 

3590 if self._sharedmask: 

3591 self._mask = self._mask.copy() 

3592 self._sharedmask = False 

3593 return self 

3594 

3595 @property 

3596 def sharedmask(self): 

3597 """ Share status of the mask (read-only). """ 

3598 return self._sharedmask 

3599 

3600 def shrink_mask(self): 

3601 """ 

3602 Reduce a mask to nomask when possible. 

3603 

3604 Parameters 

3605 ---------- 

3606 None 

3607 

3608 Returns 

3609 ------- 

3610 None 

3611 

3612 Examples 

3613 -------- 

3614 >>> x = np.ma.array([[1,2 ], [3, 4]], mask=[0]*4) 

3615 >>> x.mask 

3616 array([[False, False], 

3617 [False, False]]) 

3618 >>> x.shrink_mask() 

3619 masked_array( 

3620 data=[[1, 2], 

3621 [3, 4]], 

3622 mask=False, 

3623 fill_value=999999) 

3624 >>> x.mask 

3625 False 

3626 

3627 """ 

3628 self._mask = _shrink_mask(self._mask) 

3629 return self 

3630 

3631 @property 

3632 def baseclass(self): 

3633 """ Class of the underlying data (read-only). """ 

3634 return self._baseclass 

3635 

3636 def _get_data(self): 

3637 """ 

3638 Returns the underlying data, as a view of the masked array. 

3639 

3640 If the underlying data is a subclass of :class:`numpy.ndarray`, it is 

3641 returned as such. 

3642 

3643 >>> x = np.ma.array(np.matrix([[1, 2], [3, 4]]), mask=[[0, 1], [1, 0]]) 

3644 >>> x.data 

3645 matrix([[1, 2], 

3646 [3, 4]]) 

3647 

3648 The type of the data can be accessed through the :attr:`baseclass` 

3649 attribute. 

3650 """ 

3651 return ndarray.view(self, self._baseclass) 

3652 

3653 _data = property(fget=_get_data) 

3654 data = property(fget=_get_data) 

3655 

3656 @property 

3657 def flat(self): 

3658 """ Return a flat iterator, or set a flattened version of self to value. """ 

3659 return MaskedIterator(self) 

3660 

3661 @flat.setter 

3662 def flat(self, value): 

3663 y = self.ravel() 

3664 y[:] = value 

3665 

3666 @property 

3667 def fill_value(self): 

3668 """ 

3669 The filling value of the masked array is a scalar. When setting, None 

3670 will set to a default based on the data type. 

3671 

3672 Examples 

3673 -------- 

3674 >>> for dt in [np.int32, np.int64, np.float64, np.complex128]: 

3675 ... np.ma.array([0, 1], dtype=dt).get_fill_value() 

3676 ... 

3677 999999 

3678 999999 

3679 1e+20 

3680 (1e+20+0j) 

3681 

3682 >>> x = np.ma.array([0, 1.], fill_value=-np.inf) 

3683 >>> x.fill_value 

3684 -inf 

3685 >>> x.fill_value = np.pi 

3686 >>> x.fill_value 

3687 3.1415926535897931 # may vary 

3688 

3689 Reset to default: 

3690 

3691 >>> x.fill_value = None 

3692 >>> x.fill_value 

3693 1e+20 

3694 

3695 """ 

3696 if self._fill_value is None: 

3697 self._fill_value = _check_fill_value(None, self.dtype) 

3698 

3699 # Temporary workaround to account for the fact that str and bytes 

3700 # scalars cannot be indexed with (), whereas all other numpy 

3701 # scalars can. See issues #7259 and #7267. 

3702 # The if-block can be removed after #7267 has been fixed. 

3703 if isinstance(self._fill_value, ndarray): 

3704 return self._fill_value[()] 

3705 return self._fill_value 

3706 

3707 @fill_value.setter 

3708 def fill_value(self, value=None): 

3709 target = _check_fill_value(value, self.dtype) 

3710 if not target.ndim == 0: 

3711 # 2019-11-12, 1.18.0 

3712 warnings.warn( 

3713 "Non-scalar arrays for the fill value are deprecated. Use " 

3714 "arrays with scalar values instead. The filled function " 

3715 "still supports any array as `fill_value`.", 

3716 DeprecationWarning, stacklevel=2) 

3717 

3718 _fill_value = self._fill_value 

3719 if _fill_value is None: 

3720 # Create the attribute if it was undefined 

3721 self._fill_value = target 

3722 else: 

3723 # Don't overwrite the attribute, just fill it (for propagation) 

3724 _fill_value[()] = target 

3725 

3726 # kept for compatibility 

3727 get_fill_value = fill_value.fget 

3728 set_fill_value = fill_value.fset 

3729 

3730 def filled(self, fill_value=None): 

3731 """ 

3732 Return a copy of self, with masked values filled with a given value. 

3733 **However**, if there are no masked values to fill, self will be 

3734 returned instead as an ndarray. 

3735 

3736 Parameters 

3737 ---------- 

3738 fill_value : array_like, optional 

3739 The value to use for invalid entries. Can be scalar or non-scalar. 

3740 If non-scalar, the resulting ndarray must be broadcastable over 

3741 input array. Default is None, in which case, the `fill_value` 

3742 attribute of the array is used instead. 

3743 

3744 Returns 

3745 ------- 

3746 filled_array : ndarray 

3747 A copy of ``self`` with invalid entries replaced by *fill_value* 

3748 (be it the function argument or the attribute of ``self``), or 

3749 ``self`` itself as an ndarray if there are no invalid entries to 

3750 be replaced. 

3751 

3752 Notes 

3753 ----- 

3754 The result is **not** a MaskedArray! 

3755 

3756 Examples 

3757 -------- 

3758 >>> x = np.ma.array([1,2,3,4,5], mask=[0,0,1,0,1], fill_value=-999) 

3759 >>> x.filled() 

3760 array([ 1, 2, -999, 4, -999]) 

3761 >>> x.filled(fill_value=1000) 

3762 array([ 1, 2, 1000, 4, 1000]) 

3763 >>> type(x.filled()) 

3764 <class 'numpy.ndarray'> 

3765 

3766 Subclassing is preserved. This means that if, e.g., the data part of 

3767 the masked array is a recarray, `filled` returns a recarray: 

3768 

3769 >>> x = np.array([(-1, 2), (-3, 4)], dtype='i8,i8').view(np.recarray) 

3770 >>> m = np.ma.array(x, mask=[(True, False), (False, True)]) 

3771 >>> m.filled() 

3772 rec.array([(999999, 2), ( -3, 999999)], 

3773 dtype=[('f0', '<i8'), ('f1', '<i8')]) 

3774 """ 

3775 m = self._mask 

3776 if m is nomask: 

3777 return self._data 

3778 

3779 if fill_value is None: 

3780 fill_value = self.fill_value 

3781 else: 

3782 fill_value = _check_fill_value(fill_value, self.dtype) 

3783 

3784 if self is masked_singleton: 

3785 return np.asanyarray(fill_value) 

3786 

3787 if m.dtype.names is not None: 

3788 result = self._data.copy('K') 

3789 _recursive_filled(result, self._mask, fill_value) 

3790 elif not m.any(): 

3791 return self._data 

3792 else: 

3793 result = self._data.copy('K') 

3794 try: 

3795 np.copyto(result, fill_value, where=m) 

3796 except (TypeError, AttributeError): 

3797 fill_value = narray(fill_value, dtype=object) 

3798 d = result.astype(object) 

3799 result = np.choose(m, (d, fill_value)) 

3800 except IndexError: 

3801 # ok, if scalar 

3802 if self._data.shape: 

3803 raise 

3804 elif m: 

3805 result = np.array(fill_value, dtype=self.dtype) 

3806 else: 

3807 result = self._data 

3808 return result 

3809 

3810 def compressed(self): 

3811 """ 

3812 Return all the non-masked data as a 1-D array. 

3813 

3814 Returns 

3815 ------- 

3816 data : ndarray 

3817 A new `ndarray` holding the non-masked data is returned. 

3818 

3819 Notes 

3820 ----- 

3821 The result is **not** a MaskedArray! 

3822 

3823 Examples 

3824 -------- 

3825 >>> x = np.ma.array(np.arange(5), mask=[0]*2 + [1]*3) 

3826 >>> x.compressed() 

3827 array([0, 1]) 

3828 >>> type(x.compressed()) 

3829 <class 'numpy.ndarray'> 

3830 

3831 """ 

3832 data = ndarray.ravel(self._data) 

3833 if self._mask is not nomask: 

3834 data = data.compress(np.logical_not(ndarray.ravel(self._mask))) 

3835 return data 

3836 

3837 def compress(self, condition, axis=None, out=None): 

3838 """ 

3839 Return `a` where condition is ``True``. 

3840 

3841 If condition is a `MaskedArray`, missing values are considered 

3842 as ``False``. 

3843 

3844 Parameters 

3845 ---------- 

3846 condition : var 

3847 Boolean 1-d array selecting which entries to return. If len(condition) 

3848 is less than the size of a along the axis, then output is truncated 

3849 to length of condition array. 

3850 axis : {None, int}, optional 

3851 Axis along which the operation must be performed. 

3852 out : {None, ndarray}, optional 

3853 Alternative output array in which to place the result. It must have 

3854 the same shape as the expected output but the type will be cast if 

3855 necessary. 

3856 

3857 Returns 

3858 ------- 

3859 result : MaskedArray 

3860 A :class:`MaskedArray` object. 

3861 

3862 Notes 

3863 ----- 

3864 Please note the difference with :meth:`compressed` ! 

3865 The output of :meth:`compress` has a mask, the output of 

3866 :meth:`compressed` does not. 

3867 

3868 Examples 

3869 -------- 

3870 >>> x = np.ma.array([[1,2,3],[4,5,6],[7,8,9]], mask=[0] + [1,0]*4) 

3871 >>> x 

3872 masked_array( 

3873 data=[[1, --, 3], 

3874 [--, 5, --], 

3875 [7, --, 9]], 

3876 mask=[[False, True, False], 

3877 [ True, False, True], 

3878 [False, True, False]], 

3879 fill_value=999999) 

3880 >>> x.compress([1, 0, 1]) 

3881 masked_array(data=[1, 3], 

3882 mask=[False, False], 

3883 fill_value=999999) 

3884 

3885 >>> x.compress([1, 0, 1], axis=1) 

3886 masked_array( 

3887 data=[[1, 3], 

3888 [--, --], 

3889 [7, 9]], 

3890 mask=[[False, False], 

3891 [ True, True], 

3892 [False, False]], 

3893 fill_value=999999) 

3894 

3895 """ 

3896 # Get the basic components 

3897 (_data, _mask) = (self._data, self._mask) 

3898 

3899 # Force the condition to a regular ndarray and forget the missing 

3900 # values. 

3901 condition = np.array(condition, copy=False, subok=False) 

3902 

3903 _new = _data.compress(condition, axis=axis, out=out).view(type(self)) 

3904 _new._update_from(self) 

3905 if _mask is not nomask: 

3906 _new._mask = _mask.compress(condition, axis=axis) 

3907 return _new 

3908 

3909 def _insert_masked_print(self): 

3910 """ 

3911 Replace masked values with masked_print_option, casting all innermost 

3912 dtypes to object. 

3913 """ 

3914 if masked_print_option.enabled(): 

3915 mask = self._mask 

3916 if mask is nomask: 

3917 res = self._data 

3918 else: 

3919 # convert to object array to make filled work 

3920 data = self._data 

3921 # For big arrays, to avoid a costly conversion to the 

3922 # object dtype, extract the corners before the conversion. 

3923 print_width = (self._print_width if self.ndim > 1 

3924 else self._print_width_1d) 

3925 for axis in range(self.ndim): 

3926 if data.shape[axis] > print_width: 

3927 ind = print_width // 2 

3928 arr = np.split(data, (ind, -ind), axis=axis) 

3929 data = np.concatenate((arr[0], arr[2]), axis=axis) 

3930 arr = np.split(mask, (ind, -ind), axis=axis) 

3931 mask = np.concatenate((arr[0], arr[2]), axis=axis) 

3932 

3933 rdtype = _replace_dtype_fields(self.dtype, "O") 

3934 res = data.astype(rdtype) 

3935 _recursive_printoption(res, mask, masked_print_option) 

3936 else: 

3937 res = self.filled(self.fill_value) 

3938 return res 

3939 

3940 def __str__(self): 

3941 return str(self._insert_masked_print()) 

3942 

3943 def __repr__(self): 

3944 """ 

3945 Literal string representation. 

3946 

3947 """ 

3948 if self._baseclass is np.ndarray: 

3949 name = 'array' 

3950 else: 

3951 name = self._baseclass.__name__ 

3952 

3953 

3954 # 2016-11-19: Demoted to legacy format 

3955 if np.get_printoptions()['legacy'] == '1.13': 

3956 is_long = self.ndim > 1 

3957 parameters = dict( 

3958 name=name, 

3959 nlen=" " * len(name), 

3960 data=str(self), 

3961 mask=str(self._mask), 

3962 fill=str(self.fill_value), 

3963 dtype=str(self.dtype) 

3964 ) 

3965 is_structured = bool(self.dtype.names) 

3966 key = '{}_{}'.format( 

3967 'long' if is_long else 'short', 

3968 'flx' if is_structured else 'std' 

3969 ) 

3970 return _legacy_print_templates[key] % parameters 

3971 

3972 prefix = f"masked_{name}(" 

3973 

3974 dtype_needed = ( 

3975 not np.core.arrayprint.dtype_is_implied(self.dtype) or 

3976 np.all(self.mask) or 

3977 self.size == 0 

3978 ) 

3979 

3980 # determine which keyword args need to be shown 

3981 keys = ['data', 'mask', 'fill_value'] 

3982 if dtype_needed: 

3983 keys.append('dtype') 

3984 

3985 # array has only one row (non-column) 

3986 is_one_row = builtins.all(dim == 1 for dim in self.shape[:-1]) 

3987 

3988 # choose what to indent each keyword with 

3989 min_indent = 2 

3990 if is_one_row: 

3991 # first key on the same line as the type, remaining keys 

3992 # aligned by equals 

3993 indents = {} 

3994 indents[keys[0]] = prefix 

3995 for k in keys[1:]: 

3996 n = builtins.max(min_indent, len(prefix + keys[0]) - len(k)) 

3997 indents[k] = ' ' * n 

3998 prefix = '' # absorbed into the first indent 

3999 else: 

4000 # each key on its own line, indented by two spaces 

4001 indents = {k: ' ' * min_indent for k in keys} 

4002 prefix = prefix + '\n' # first key on the next line 

4003 

4004 # format the field values 

4005 reprs = {} 

4006 reprs['data'] = np.array2string( 

4007 self._insert_masked_print(), 

4008 separator=", ", 

4009 prefix=indents['data'] + 'data=', 

4010 suffix=',') 

4011 reprs['mask'] = np.array2string( 

4012 self._mask, 

4013 separator=", ", 

4014 prefix=indents['mask'] + 'mask=', 

4015 suffix=',') 

4016 reprs['fill_value'] = repr(self.fill_value) 

4017 if dtype_needed: 

4018 reprs['dtype'] = np.core.arrayprint.dtype_short_repr(self.dtype) 

4019 

4020 # join keys with values and indentations 

4021 result = ',\n'.join( 

4022 '{}{}={}'.format(indents[k], k, reprs[k]) 

4023 for k in keys 

4024 ) 

4025 return prefix + result + ')' 

4026 

4027 def _delegate_binop(self, other): 

4028 # This emulates the logic in 

4029 # private/binop_override.h:forward_binop_should_defer 

4030 if isinstance(other, type(self)): 

4031 return False 

4032 array_ufunc = getattr(other, "__array_ufunc__", False) 

4033 if array_ufunc is False: 

4034 other_priority = getattr(other, "__array_priority__", -1000000) 

4035 return self.__array_priority__ < other_priority 

4036 else: 

4037 # If array_ufunc is not None, it will be called inside the ufunc; 

4038 # None explicitly tells us to not call the ufunc, i.e., defer. 

4039 return array_ufunc is None 

4040 

4041 def _comparison(self, other, compare): 

4042 """Compare self with other using operator.eq or operator.ne. 

4043 

4044 When either of the elements is masked, the result is masked as well, 

4045 but the underlying boolean data are still set, with self and other 

4046 considered equal if both are masked, and unequal otherwise. 

4047 

4048 For structured arrays, all fields are combined, with masked values 

4049 ignored. The result is masked if all fields were masked, with self 

4050 and other considered equal only if both were fully masked. 

4051 """ 

4052 omask = getmask(other) 

4053 smask = self.mask 

4054 mask = mask_or(smask, omask, copy=True) 

4055 

4056 odata = getdata(other) 

4057 if mask.dtype.names is not None: 

4058 # For possibly masked structured arrays we need to be careful, 

4059 # since the standard structured array comparison will use all 

4060 # fields, masked or not. To avoid masked fields influencing the 

4061 # outcome, we set all masked fields in self to other, so they'll 

4062 # count as equal. To prepare, we ensure we have the right shape. 

4063 broadcast_shape = np.broadcast(self, odata).shape 

4064 sbroadcast = np.broadcast_to(self, broadcast_shape, subok=True) 

4065 sbroadcast._mask = mask 

4066 sdata = sbroadcast.filled(odata) 

4067 # Now take care of the mask; the merged mask should have an item 

4068 # masked if all fields were masked (in one and/or other). 

4069 mask = (mask == np.ones((), mask.dtype)) 

4070 

4071 else: 

4072 # For regular arrays, just use the data as they come. 

4073 sdata = self.data 

4074 

4075 check = compare(sdata, odata) 

4076 

4077 if isinstance(check, (np.bool_, bool)): 

4078 return masked if mask else check 

4079 

4080 if mask is not nomask: 

4081 # Adjust elements that were masked, which should be treated 

4082 # as equal if masked in both, unequal if masked in one. 

4083 # Note that this works automatically for structured arrays too. 

4084 check = np.where(mask, compare(smask, omask), check) 

4085 if mask.shape != check.shape: 

4086 # Guarantee consistency of the shape, making a copy since the 

4087 # the mask may need to get written to later. 

4088 mask = np.broadcast_to(mask, check.shape).copy() 

4089 

4090 check = check.view(type(self)) 

4091 check._update_from(self) 

4092 check._mask = mask 

4093 

4094 # Cast fill value to bool_ if needed. If it cannot be cast, the 

4095 # default boolean fill value is used. 

4096 if check._fill_value is not None: 

4097 try: 

4098 fill = _check_fill_value(check._fill_value, np.bool_) 

4099 except (TypeError, ValueError): 

4100 fill = _check_fill_value(None, np.bool_) 

4101 check._fill_value = fill 

4102 

4103 return check 

4104 

4105 def __eq__(self, other): 

4106 """Check whether other equals self elementwise. 

4107 

4108 When either of the elements is masked, the result is masked as well, 

4109 but the underlying boolean data are still set, with self and other 

4110 considered equal if both are masked, and unequal otherwise. 

4111 

4112 For structured arrays, all fields are combined, with masked values 

4113 ignored. The result is masked if all fields were masked, with self 

4114 and other considered equal only if both were fully masked. 

4115 """ 

4116 return self._comparison(other, operator.eq) 

4117 

4118 def __ne__(self, other): 

4119 """Check whether other does not equal self elementwise. 

4120 

4121 When either of the elements is masked, the result is masked as well, 

4122 but the underlying boolean data are still set, with self and other 

4123 considered equal if both are masked, and unequal otherwise. 

4124 

4125 For structured arrays, all fields are combined, with masked values 

4126 ignored. The result is masked if all fields were masked, with self 

4127 and other considered equal only if both were fully masked. 

4128 """ 

4129 return self._comparison(other, operator.ne) 

4130 

4131 def __add__(self, other): 

4132 """ 

4133 Add self to other, and return a new masked array. 

4134 

4135 """ 

4136 if self._delegate_binop(other): 

4137 return NotImplemented 

4138 return add(self, other) 

4139 

4140 def __radd__(self, other): 

4141 """ 

4142 Add other to self, and return a new masked array. 

4143 

4144 """ 

4145 # In analogy with __rsub__ and __rdiv__, use original order: 

4146 # we get here from `other + self`. 

4147 return add(other, self) 

4148 

4149 def __sub__(self, other): 

4150 """ 

4151 Subtract other from self, and return a new masked array. 

4152 

4153 """ 

4154 if self._delegate_binop(other): 

4155 return NotImplemented 

4156 return subtract(self, other) 

4157 

4158 def __rsub__(self, other): 

4159 """ 

4160 Subtract self from other, and return a new masked array. 

4161 

4162 """ 

4163 return subtract(other, self) 

4164 

4165 def __mul__(self, other): 

4166 "Multiply self by other, and return a new masked array." 

4167 if self._delegate_binop(other): 

4168 return NotImplemented 

4169 return multiply(self, other) 

4170 

4171 def __rmul__(self, other): 

4172 """ 

4173 Multiply other by self, and return a new masked array. 

4174 

4175 """ 

4176 # In analogy with __rsub__ and __rdiv__, use original order: 

4177 # we get here from `other * self`. 

4178 return multiply(other, self) 

4179 

4180 def __div__(self, other): 

4181 """ 

4182 Divide other into self, and return a new masked array. 

4183 

4184 """ 

4185 if self._delegate_binop(other): 

4186 return NotImplemented 

4187 return divide(self, other) 

4188 

4189 def __truediv__(self, other): 

4190 """ 

4191 Divide other into self, and return a new masked array. 

4192 

4193 """ 

4194 if self._delegate_binop(other): 

4195 return NotImplemented 

4196 return true_divide(self, other) 

4197 

4198 def __rtruediv__(self, other): 

4199 """ 

4200 Divide self into other, and return a new masked array. 

4201 

4202 """ 

4203 return true_divide(other, self) 

4204 

4205 def __floordiv__(self, other): 

4206 """ 

4207 Divide other into self, and return a new masked array. 

4208 

4209 """ 

4210 if self._delegate_binop(other): 

4211 return NotImplemented 

4212 return floor_divide(self, other) 

4213 

4214 def __rfloordiv__(self, other): 

4215 """ 

4216 Divide self into other, and return a new masked array. 

4217 

4218 """ 

4219 return floor_divide(other, self) 

4220 

4221 def __pow__(self, other): 

4222 """ 

4223 Raise self to the power other, masking the potential NaNs/Infs 

4224 

4225 """ 

4226 if self._delegate_binop(other): 

4227 return NotImplemented 

4228 return power(self, other) 

4229 

4230 def __rpow__(self, other): 

4231 """ 

4232 Raise other to the power self, masking the potential NaNs/Infs 

4233 

4234 """ 

4235 return power(other, self) 

4236 

4237 def __iadd__(self, other): 

4238 """ 

4239 Add other to self in-place. 

4240 

4241 """ 

4242 m = getmask(other) 

4243 if self._mask is nomask: 

4244 if m is not nomask and m.any(): 

4245 self._mask = make_mask_none(self.shape, self.dtype) 

4246 self._mask += m 

4247 else: 

4248 if m is not nomask: 

4249 self._mask += m 

4250 self._data.__iadd__(np.where(self._mask, self.dtype.type(0), 

4251 getdata(other))) 

4252 return self 

4253 

4254 def __isub__(self, other): 

4255 """ 

4256 Subtract other from self in-place. 

4257 

4258 """ 

4259 m = getmask(other) 

4260 if self._mask is nomask: 

4261 if m is not nomask and m.any(): 

4262 self._mask = make_mask_none(self.shape, self.dtype) 

4263 self._mask += m 

4264 elif m is not nomask: 

4265 self._mask += m 

4266 self._data.__isub__(np.where(self._mask, self.dtype.type(0), 

4267 getdata(other))) 

4268 return self 

4269 

4270 def __imul__(self, other): 

4271 """ 

4272 Multiply self by other in-place. 

4273 

4274 """ 

4275 m = getmask(other) 

4276 if self._mask is nomask: 

4277 if m is not nomask and m.any(): 

4278 self._mask = make_mask_none(self.shape, self.dtype) 

4279 self._mask += m 

4280 elif m is not nomask: 

4281 self._mask += m 

4282 self._data.__imul__(np.where(self._mask, self.dtype.type(1), 

4283 getdata(other))) 

4284 return self 

4285 

4286 def __idiv__(self, other): 

4287 """ 

4288 Divide self by other in-place. 

4289 

4290 """ 

4291 other_data = getdata(other) 

4292 dom_mask = _DomainSafeDivide().__call__(self._data, other_data) 

4293 other_mask = getmask(other) 

4294 new_mask = mask_or(other_mask, dom_mask) 

4295 # The following 3 lines control the domain filling 

4296 if dom_mask.any(): 

4297 (_, fval) = ufunc_fills[np.divide] 

4298 other_data = np.where(dom_mask, fval, other_data) 

4299 self._mask |= new_mask 

4300 self._data.__idiv__(np.where(self._mask, self.dtype.type(1), 

4301 other_data)) 

4302 return self 

4303 

4304 def __ifloordiv__(self, other): 

4305 """ 

4306 Floor divide self by other in-place. 

4307 

4308 """ 

4309 other_data = getdata(other) 

4310 dom_mask = _DomainSafeDivide().__call__(self._data, other_data) 

4311 other_mask = getmask(other) 

4312 new_mask = mask_or(other_mask, dom_mask) 

4313 # The following 3 lines control the domain filling 

4314 if dom_mask.any(): 

4315 (_, fval) = ufunc_fills[np.floor_divide] 

4316 other_data = np.where(dom_mask, fval, other_data) 

4317 self._mask |= new_mask 

4318 self._data.__ifloordiv__(np.where(self._mask, self.dtype.type(1), 

4319 other_data)) 

4320 return self 

4321 

4322 def __itruediv__(self, other): 

4323 """ 

4324 True divide self by other in-place. 

4325 

4326 """ 

4327 other_data = getdata(other) 

4328 dom_mask = _DomainSafeDivide().__call__(self._data, other_data) 

4329 other_mask = getmask(other) 

4330 new_mask = mask_or(other_mask, dom_mask) 

4331 # The following 3 lines control the domain filling 

4332 if dom_mask.any(): 

4333 (_, fval) = ufunc_fills[np.true_divide] 

4334 other_data = np.where(dom_mask, fval, other_data) 

4335 self._mask |= new_mask 

4336 self._data.__itruediv__(np.where(self._mask, self.dtype.type(1), 

4337 other_data)) 

4338 return self 

4339 

4340 def __ipow__(self, other): 

4341 """ 

4342 Raise self to the power other, in place. 

4343 

4344 """ 

4345 other_data = getdata(other) 

4346 other_mask = getmask(other) 

4347 with np.errstate(divide='ignore', invalid='ignore'): 

4348 self._data.__ipow__(np.where(self._mask, self.dtype.type(1), 

4349 other_data)) 

4350 invalid = np.logical_not(np.isfinite(self._data)) 

4351 if invalid.any(): 

4352 if self._mask is not nomask: 

4353 self._mask |= invalid 

4354 else: 

4355 self._mask = invalid 

4356 np.copyto(self._data, self.fill_value, where=invalid) 

4357 new_mask = mask_or(other_mask, invalid) 

4358 self._mask = mask_or(self._mask, new_mask) 

4359 return self 

4360 

4361 def __float__(self): 

4362 """ 

4363 Convert to float. 

4364 

4365 """ 

4366 if self.size > 1: 

4367 raise TypeError("Only length-1 arrays can be converted " 

4368 "to Python scalars") 

4369 elif self._mask: 

4370 warnings.warn("Warning: converting a masked element to nan.", stacklevel=2) 

4371 return np.nan 

4372 return float(self.item()) 

4373 

4374 def __int__(self): 

4375 """ 

4376 Convert to int. 

4377 

4378 """ 

4379 if self.size > 1: 

4380 raise TypeError("Only length-1 arrays can be converted " 

4381 "to Python scalars") 

4382 elif self._mask: 

4383 raise MaskError('Cannot convert masked element to a Python int.') 

4384 return int(self.item()) 

4385 

4386 @property 

4387 def imag(self): 

4388 """ 

4389 The imaginary part of the masked array. 

4390 

4391 This property is a view on the imaginary part of this `MaskedArray`. 

4392 

4393 See Also 

4394 -------- 

4395 real 

4396 

4397 Examples 

4398 -------- 

4399 >>> x = np.ma.array([1+1.j, -2j, 3.45+1.6j], mask=[False, True, False]) 

4400 >>> x.imag 

4401 masked_array(data=[1.0, --, 1.6], 

4402 mask=[False, True, False], 

4403 fill_value=1e+20) 

4404 

4405 """ 

4406 result = self._data.imag.view(type(self)) 

4407 result.__setmask__(self._mask) 

4408 return result 

4409 

4410 # kept for compatibility 

4411 get_imag = imag.fget 

4412 

4413 @property 

4414 def real(self): 

4415 """ 

4416 The real part of the masked array. 

4417 

4418 This property is a view on the real part of this `MaskedArray`. 

4419 

4420 See Also 

4421 -------- 

4422 imag 

4423 

4424 Examples 

4425 -------- 

4426 >>> x = np.ma.array([1+1.j, -2j, 3.45+1.6j], mask=[False, True, False]) 

4427 >>> x.real 

4428 masked_array(data=[1.0, --, 3.45], 

4429 mask=[False, True, False], 

4430 fill_value=1e+20) 

4431 

4432 """ 

4433 result = self._data.real.view(type(self)) 

4434 result.__setmask__(self._mask) 

4435 return result 

4436 

4437 # kept for compatibility 

4438 get_real = real.fget 

4439 

4440 def count(self, axis=None, keepdims=np._NoValue): 

4441 """ 

4442 Count the non-masked elements of the array along the given axis. 

4443 

4444 Parameters 

4445 ---------- 

4446 axis : None or int or tuple of ints, optional 

4447 Axis or axes along which the count is performed. 

4448 The default, None, performs the count over all 

4449 the dimensions of the input array. `axis` may be negative, in 

4450 which case it counts from the last to the first axis. 

4451 

4452 .. versionadded:: 1.10.0 

4453 

4454 If this is a tuple of ints, the count is performed on multiple 

4455 axes, instead of a single axis or all the axes as before. 

4456 keepdims : bool, optional 

4457 If this is set to True, the axes which are reduced are left 

4458 in the result as dimensions with size one. With this option, 

4459 the result will broadcast correctly against the array. 

4460 

4461 Returns 

4462 ------- 

4463 result : ndarray or scalar 

4464 An array with the same shape as the input array, with the specified 

4465 axis removed. If the array is a 0-d array, or if `axis` is None, a 

4466 scalar is returned. 

4467 

4468 See Also 

4469 -------- 

4470 count_masked : Count masked elements in array or along a given axis. 

4471 

4472 Examples 

4473 -------- 

4474 >>> import numpy.ma as ma 

4475 >>> a = ma.arange(6).reshape((2, 3)) 

4476 >>> a[1, :] = ma.masked 

4477 >>> a 

4478 masked_array( 

4479 data=[[0, 1, 2], 

4480 [--, --, --]], 

4481 mask=[[False, False, False], 

4482 [ True, True, True]], 

4483 fill_value=999999) 

4484 >>> a.count() 

4485 3 

4486 

4487 When the `axis` keyword is specified an array of appropriate size is 

4488 returned. 

4489 

4490 >>> a.count(axis=0) 

4491 array([1, 1, 1]) 

4492 >>> a.count(axis=1) 

4493 array([3, 0]) 

4494 

4495 """ 

4496 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

4497 

4498 m = self._mask 

4499 # special case for matrices (we assume no other subclasses modify 

4500 # their dimensions) 

4501 if isinstance(self.data, np.matrix): 

4502 if m is nomask: 

4503 m = np.zeros(self.shape, dtype=np.bool_) 

4504 m = m.view(type(self.data)) 

4505 

4506 if m is nomask: 

4507 # compare to _count_reduce_items in _methods.py 

4508 

4509 if self.shape == (): 

4510 if axis not in (None, 0): 

4511 raise np.AxisError(axis=axis, ndim=self.ndim) 

4512 return 1 

4513 elif axis is None: 

4514 if kwargs.get('keepdims', False): 

4515 return np.array(self.size, dtype=np.intp, ndmin=self.ndim) 

4516 return self.size 

4517 

4518 axes = normalize_axis_tuple(axis, self.ndim) 

4519 items = 1 

4520 for ax in axes: 

4521 items *= self.shape[ax] 

4522 

4523 if kwargs.get('keepdims', False): 

4524 out_dims = list(self.shape) 

4525 for a in axes: 

4526 out_dims[a] = 1 

4527 else: 

4528 out_dims = [d for n, d in enumerate(self.shape) 

4529 if n not in axes] 

4530 # make sure to return a 0-d array if axis is supplied 

4531 return np.full(out_dims, items, dtype=np.intp) 

4532 

4533 # take care of the masked singleton 

4534 if self is masked: 

4535 return 0 

4536 

4537 return (~m).sum(axis=axis, dtype=np.intp, **kwargs) 

4538 

4539 def ravel(self, order='C'): 

4540 """ 

4541 Returns a 1D version of self, as a view. 

4542 

4543 Parameters 

4544 ---------- 

4545 order : {'C', 'F', 'A', 'K'}, optional 

4546 The elements of `a` are read using this index order. 'C' means to 

4547 index the elements in C-like order, with the last axis index 

4548 changing fastest, back to the first axis index changing slowest. 

4549 'F' means to index the elements in Fortran-like index order, with 

4550 the first index changing fastest, and the last index changing 

4551 slowest. Note that the 'C' and 'F' options take no account of the 

4552 memory layout of the underlying array, and only refer to the order 

4553 of axis indexing. 'A' means to read the elements in Fortran-like 

4554 index order if `m` is Fortran *contiguous* in memory, C-like order 

4555 otherwise. 'K' means to read the elements in the order they occur 

4556 in memory, except for reversing the data when strides are negative. 

4557 By default, 'C' index order is used. 

4558 

4559 Returns 

4560 ------- 

4561 MaskedArray 

4562 Output view is of shape ``(self.size,)`` (or 

4563 ``(np.ma.product(self.shape),)``). 

4564 

4565 Examples 

4566 -------- 

4567 >>> x = np.ma.array([[1,2,3],[4,5,6],[7,8,9]], mask=[0] + [1,0]*4) 

4568 >>> x 

4569 masked_array( 

4570 data=[[1, --, 3], 

4571 [--, 5, --], 

4572 [7, --, 9]], 

4573 mask=[[False, True, False], 

4574 [ True, False, True], 

4575 [False, True, False]], 

4576 fill_value=999999) 

4577 >>> x.ravel() 

4578 masked_array(data=[1, --, 3, --, 5, --, 7, --, 9], 

4579 mask=[False, True, False, True, False, True, False, True, 

4580 False], 

4581 fill_value=999999) 

4582 

4583 """ 

4584 r = ndarray.ravel(self._data, order=order).view(type(self)) 

4585 r._update_from(self) 

4586 if self._mask is not nomask: 

4587 r._mask = ndarray.ravel(self._mask, order=order).reshape(r.shape) 

4588 else: 

4589 r._mask = nomask 

4590 return r 

4591 

4592 

4593 def reshape(self, *s, **kwargs): 

4594 """ 

4595 Give a new shape to the array without changing its data. 

4596 

4597 Returns a masked array containing the same data, but with a new shape. 

4598 The result is a view on the original array; if this is not possible, a 

4599 ValueError is raised. 

4600 

4601 Parameters 

4602 ---------- 

4603 shape : int or tuple of ints 

4604 The new shape should be compatible with the original shape. If an 

4605 integer is supplied, then the result will be a 1-D array of that 

4606 length. 

4607 order : {'C', 'F'}, optional 

4608 Determines whether the array data should be viewed as in C 

4609 (row-major) or FORTRAN (column-major) order. 

4610 

4611 Returns 

4612 ------- 

4613 reshaped_array : array 

4614 A new view on the array. 

4615 

4616 See Also 

4617 -------- 

4618 reshape : Equivalent function in the masked array module. 

4619 numpy.ndarray.reshape : Equivalent method on ndarray object. 

4620 numpy.reshape : Equivalent function in the NumPy module. 

4621 

4622 Notes 

4623 ----- 

4624 The reshaping operation cannot guarantee that a copy will not be made, 

4625 to modify the shape in place, use ``a.shape = s`` 

4626 

4627 Examples 

4628 -------- 

4629 >>> x = np.ma.array([[1,2],[3,4]], mask=[1,0,0,1]) 

4630 >>> x 

4631 masked_array( 

4632 data=[[--, 2], 

4633 [3, --]], 

4634 mask=[[ True, False], 

4635 [False, True]], 

4636 fill_value=999999) 

4637 >>> x = x.reshape((4,1)) 

4638 >>> x 

4639 masked_array( 

4640 data=[[--], 

4641 [2], 

4642 [3], 

4643 [--]], 

4644 mask=[[ True], 

4645 [False], 

4646 [False], 

4647 [ True]], 

4648 fill_value=999999) 

4649 

4650 """ 

4651 kwargs.update(order=kwargs.get('order', 'C')) 

4652 result = self._data.reshape(*s, **kwargs).view(type(self)) 

4653 result._update_from(self) 

4654 mask = self._mask 

4655 if mask is not nomask: 

4656 result._mask = mask.reshape(*s, **kwargs) 

4657 return result 

4658 

4659 def resize(self, newshape, refcheck=True, order=False): 

4660 """ 

4661 .. warning:: 

4662 

4663 This method does nothing, except raise a ValueError exception. A 

4664 masked array does not own its data and therefore cannot safely be 

4665 resized in place. Use the `numpy.ma.resize` function instead. 

4666 

4667 This method is difficult to implement safely and may be deprecated in 

4668 future releases of NumPy. 

4669 

4670 """ 

4671 # Note : the 'order' keyword looks broken, let's just drop it 

4672 errmsg = "A masked array does not own its data "\ 

4673 "and therefore cannot be resized.\n" \ 

4674 "Use the numpy.ma.resize function instead." 

4675 raise ValueError(errmsg) 

4676 

4677 def put(self, indices, values, mode='raise'): 

4678 """ 

4679 Set storage-indexed locations to corresponding values. 

4680 

4681 Sets self._data.flat[n] = values[n] for each n in indices. 

4682 If `values` is shorter than `indices` then it will repeat. 

4683 If `values` has some masked values, the initial mask is updated 

4684 in consequence, else the corresponding values are unmasked. 

4685 

4686 Parameters 

4687 ---------- 

4688 indices : 1-D array_like 

4689 Target indices, interpreted as integers. 

4690 values : array_like 

4691 Values to place in self._data copy at target indices. 

4692 mode : {'raise', 'wrap', 'clip'}, optional 

4693 Specifies how out-of-bounds indices will behave. 

4694 'raise' : raise an error. 

4695 'wrap' : wrap around. 

4696 'clip' : clip to the range. 

4697 

4698 Notes 

4699 ----- 

4700 `values` can be a scalar or length 1 array. 

4701 

4702 Examples 

4703 -------- 

4704 >>> x = np.ma.array([[1,2,3],[4,5,6],[7,8,9]], mask=[0] + [1,0]*4) 

4705 >>> x 

4706 masked_array( 

4707 data=[[1, --, 3], 

4708 [--, 5, --], 

4709 [7, --, 9]], 

4710 mask=[[False, True, False], 

4711 [ True, False, True], 

4712 [False, True, False]], 

4713 fill_value=999999) 

4714 >>> x.put([0,4,8],[10,20,30]) 

4715 >>> x 

4716 masked_array( 

4717 data=[[10, --, 3], 

4718 [--, 20, --], 

4719 [7, --, 30]], 

4720 mask=[[False, True, False], 

4721 [ True, False, True], 

4722 [False, True, False]], 

4723 fill_value=999999) 

4724 

4725 >>> x.put(4,999) 

4726 >>> x 

4727 masked_array( 

4728 data=[[10, --, 3], 

4729 [--, 999, --], 

4730 [7, --, 30]], 

4731 mask=[[False, True, False], 

4732 [ True, False, True], 

4733 [False, True, False]], 

4734 fill_value=999999) 

4735 

4736 """ 

4737 # Hard mask: Get rid of the values/indices that fall on masked data 

4738 if self._hardmask and self._mask is not nomask: 

4739 mask = self._mask[indices] 

4740 indices = narray(indices, copy=False) 

4741 values = narray(values, copy=False, subok=True) 

4742 values.resize(indices.shape) 

4743 indices = indices[~mask] 

4744 values = values[~mask] 

4745 

4746 self._data.put(indices, values, mode=mode) 

4747 

4748 # short circuit if neither self nor values are masked 

4749 if self._mask is nomask and getmask(values) is nomask: 

4750 return 

4751 

4752 m = getmaskarray(self) 

4753 

4754 if getmask(values) is nomask: 

4755 m.put(indices, False, mode=mode) 

4756 else: 

4757 m.put(indices, values._mask, mode=mode) 

4758 m = make_mask(m, copy=False, shrink=True) 

4759 self._mask = m 

4760 return 

4761 

4762 def ids(self): 

4763 """ 

4764 Return the addresses of the data and mask areas. 

4765 

4766 Parameters 

4767 ---------- 

4768 None 

4769 

4770 Examples 

4771 -------- 

4772 >>> x = np.ma.array([1, 2, 3], mask=[0, 1, 1]) 

4773 >>> x.ids() 

4774 (166670640, 166659832) # may vary 

4775 

4776 If the array has no mask, the address of `nomask` is returned. This address 

4777 is typically not close to the data in memory: 

4778 

4779 >>> x = np.ma.array([1, 2, 3]) 

4780 >>> x.ids() 

4781 (166691080, 3083169284) # may vary 

4782 

4783 """ 

4784 if self._mask is nomask: 

4785 return (self.ctypes.data, id(nomask)) 

4786 return (self.ctypes.data, self._mask.ctypes.data) 

4787 

4788 def iscontiguous(self): 

4789 """ 

4790 Return a boolean indicating whether the data is contiguous. 

4791 

4792 Parameters 

4793 ---------- 

4794 None 

4795 

4796 Examples 

4797 -------- 

4798 >>> x = np.ma.array([1, 2, 3]) 

4799 >>> x.iscontiguous() 

4800 True 

4801 

4802 `iscontiguous` returns one of the flags of the masked array: 

4803 

4804 >>> x.flags 

4805 C_CONTIGUOUS : True 

4806 F_CONTIGUOUS : True 

4807 OWNDATA : False 

4808 WRITEABLE : True 

4809 ALIGNED : True 

4810 WRITEBACKIFCOPY : False 

4811 UPDATEIFCOPY : False 

4812 

4813 """ 

4814 return self.flags['CONTIGUOUS'] 

4815 

4816 def all(self, axis=None, out=None, keepdims=np._NoValue): 

4817 """ 

4818 Returns True if all elements evaluate to True. 

4819 

4820 The output array is masked where all the values along the given axis 

4821 are masked: if the output would have been a scalar and that all the 

4822 values are masked, then the output is `masked`. 

4823 

4824 Refer to `numpy.all` for full documentation. 

4825 

4826 See Also 

4827 -------- 

4828 numpy.ndarray.all : corresponding function for ndarrays 

4829 numpy.all : equivalent function 

4830 

4831 Examples 

4832 -------- 

4833 >>> np.ma.array([1,2,3]).all() 

4834 True 

4835 >>> a = np.ma.array([1,2,3], mask=True) 

4836 >>> (a.all() is np.ma.masked) 

4837 True 

4838 

4839 """ 

4840 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

4841 

4842 mask = _check_mask_axis(self._mask, axis, **kwargs) 

4843 if out is None: 

4844 d = self.filled(True).all(axis=axis, **kwargs).view(type(self)) 

4845 if d.ndim: 

4846 d.__setmask__(mask) 

4847 elif mask: 

4848 return masked 

4849 return d 

4850 self.filled(True).all(axis=axis, out=out, **kwargs) 

4851 if isinstance(out, MaskedArray): 

4852 if out.ndim or mask: 

4853 out.__setmask__(mask) 

4854 return out 

4855 

4856 def any(self, axis=None, out=None, keepdims=np._NoValue): 

4857 """ 

4858 Returns True if any of the elements of `a` evaluate to True. 

4859 

4860 Masked values are considered as False during computation. 

4861 

4862 Refer to `numpy.any` for full documentation. 

4863 

4864 See Also 

4865 -------- 

4866 numpy.ndarray.any : corresponding function for ndarrays 

4867 numpy.any : equivalent function 

4868 

4869 """ 

4870 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

4871 

4872 mask = _check_mask_axis(self._mask, axis, **kwargs) 

4873 if out is None: 

4874 d = self.filled(False).any(axis=axis, **kwargs).view(type(self)) 

4875 if d.ndim: 

4876 d.__setmask__(mask) 

4877 elif mask: 

4878 d = masked 

4879 return d 

4880 self.filled(False).any(axis=axis, out=out, **kwargs) 

4881 if isinstance(out, MaskedArray): 

4882 if out.ndim or mask: 

4883 out.__setmask__(mask) 

4884 return out 

4885 

4886 def nonzero(self): 

4887 """ 

4888 Return the indices of unmasked elements that are not zero. 

4889 

4890 Returns a tuple of arrays, one for each dimension, containing the 

4891 indices of the non-zero elements in that dimension. The corresponding 

4892 non-zero values can be obtained with:: 

4893 

4894 a[a.nonzero()] 

4895 

4896 To group the indices by element, rather than dimension, use 

4897 instead:: 

4898 

4899 np.transpose(a.nonzero()) 

4900 

4901 The result of this is always a 2d array, with a row for each non-zero 

4902 element. 

4903 

4904 Parameters 

4905 ---------- 

4906 None 

4907 

4908 Returns 

4909 ------- 

4910 tuple_of_arrays : tuple 

4911 Indices of elements that are non-zero. 

4912 

4913 See Also 

4914 -------- 

4915 numpy.nonzero : 

4916 Function operating on ndarrays. 

4917 flatnonzero : 

4918 Return indices that are non-zero in the flattened version of the input 

4919 array. 

4920 numpy.ndarray.nonzero : 

4921 Equivalent ndarray method. 

4922 count_nonzero : 

4923 Counts the number of non-zero elements in the input array. 

4924 

4925 Examples 

4926 -------- 

4927 >>> import numpy.ma as ma 

4928 >>> x = ma.array(np.eye(3)) 

4929 >>> x 

4930 masked_array( 

4931 data=[[1., 0., 0.], 

4932 [0., 1., 0.], 

4933 [0., 0., 1.]], 

4934 mask=False, 

4935 fill_value=1e+20) 

4936 >>> x.nonzero() 

4937 (array([0, 1, 2]), array([0, 1, 2])) 

4938 

4939 Masked elements are ignored. 

4940 

4941 >>> x[1, 1] = ma.masked 

4942 >>> x 

4943 masked_array( 

4944 data=[[1.0, 0.0, 0.0], 

4945 [0.0, --, 0.0], 

4946 [0.0, 0.0, 1.0]], 

4947 mask=[[False, False, False], 

4948 [False, True, False], 

4949 [False, False, False]], 

4950 fill_value=1e+20) 

4951 >>> x.nonzero() 

4952 (array([0, 2]), array([0, 2])) 

4953 

4954 Indices can also be grouped by element. 

4955 

4956 >>> np.transpose(x.nonzero()) 

4957 array([[0, 0], 

4958 [2, 2]]) 

4959 

4960 A common use for ``nonzero`` is to find the indices of an array, where 

4961 a condition is True. Given an array `a`, the condition `a` > 3 is a 

4962 boolean array and since False is interpreted as 0, ma.nonzero(a > 3) 

4963 yields the indices of the `a` where the condition is true. 

4964 

4965 >>> a = ma.array([[1,2,3],[4,5,6],[7,8,9]]) 

4966 >>> a > 3 

4967 masked_array( 

4968 data=[[False, False, False], 

4969 [ True, True, True], 

4970 [ True, True, True]], 

4971 mask=False, 

4972 fill_value=True) 

4973 >>> ma.nonzero(a > 3) 

4974 (array([1, 1, 1, 2, 2, 2]), array([0, 1, 2, 0, 1, 2])) 

4975 

4976 The ``nonzero`` method of the condition array can also be called. 

4977 

4978 >>> (a > 3).nonzero() 

4979 (array([1, 1, 1, 2, 2, 2]), array([0, 1, 2, 0, 1, 2])) 

4980 

4981 """ 

4982 return narray(self.filled(0), copy=False).nonzero() 

4983 

4984 def trace(self, offset=0, axis1=0, axis2=1, dtype=None, out=None): 

4985 """ 

4986 (this docstring should be overwritten) 

4987 """ 

4988 #!!!: implement out + test! 

4989 m = self._mask 

4990 if m is nomask: 

4991 result = super(MaskedArray, self).trace(offset=offset, axis1=axis1, 

4992 axis2=axis2, out=out) 

4993 return result.astype(dtype) 

4994 else: 

4995 D = self.diagonal(offset=offset, axis1=axis1, axis2=axis2) 

4996 return D.astype(dtype).filled(0).sum(axis=-1, out=out) 

4997 trace.__doc__ = ndarray.trace.__doc__ 

4998 

4999 def dot(self, b, out=None, strict=False): 

5000 """ 

5001 a.dot(b, out=None) 

5002 

5003 Masked dot product of two arrays. Note that `out` and `strict` are 

5004 located in different positions than in `ma.dot`. In order to 

5005 maintain compatibility with the functional version, it is 

5006 recommended that the optional arguments be treated as keyword only. 

5007 At some point that may be mandatory. 

5008 

5009 .. versionadded:: 1.10.0 

5010 

5011 Parameters 

5012 ---------- 

5013 b : masked_array_like 

5014 Inputs array. 

5015 out : masked_array, optional 

5016 Output argument. This must have the exact kind that would be 

5017 returned if it was not used. In particular, it must have the 

5018 right type, must be C-contiguous, and its dtype must be the 

5019 dtype that would be returned for `ma.dot(a,b)`. This is a 

5020 performance feature. Therefore, if these conditions are not 

5021 met, an exception is raised, instead of attempting to be 

5022 flexible. 

5023 strict : bool, optional 

5024 Whether masked data are propagated (True) or set to 0 (False) 

5025 for the computation. Default is False. Propagating the mask 

5026 means that if a masked value appears in a row or column, the 

5027 whole row or column is considered masked. 

5028 

5029 .. versionadded:: 1.10.2 

5030 

5031 See Also 

5032 -------- 

5033 numpy.ma.dot : equivalent function 

5034 

5035 """ 

5036 return dot(self, b, out=out, strict=strict) 

5037 

5038 def sum(self, axis=None, dtype=None, out=None, keepdims=np._NoValue): 

5039 """ 

5040 Return the sum of the array elements over the given axis. 

5041 

5042 Masked elements are set to 0 internally. 

5043 

5044 Refer to `numpy.sum` for full documentation. 

5045 

5046 See Also 

5047 -------- 

5048 numpy.ndarray.sum : corresponding function for ndarrays 

5049 numpy.sum : equivalent function 

5050 

5051 Examples 

5052 -------- 

5053 >>> x = np.ma.array([[1,2,3],[4,5,6],[7,8,9]], mask=[0] + [1,0]*4) 

5054 >>> x 

5055 masked_array( 

5056 data=[[1, --, 3], 

5057 [--, 5, --], 

5058 [7, --, 9]], 

5059 mask=[[False, True, False], 

5060 [ True, False, True], 

5061 [False, True, False]], 

5062 fill_value=999999) 

5063 >>> x.sum() 

5064 25 

5065 >>> x.sum(axis=1) 

5066 masked_array(data=[4, 5, 16], 

5067 mask=[False, False, False], 

5068 fill_value=999999) 

5069 >>> x.sum(axis=0) 

5070 masked_array(data=[8, 5, 12], 

5071 mask=[False, False, False], 

5072 fill_value=999999) 

5073 >>> print(type(x.sum(axis=0, dtype=np.int64)[0])) 

5074 <class 'numpy.int64'> 

5075 

5076 """ 

5077 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

5078 

5079 _mask = self._mask 

5080 newmask = _check_mask_axis(_mask, axis, **kwargs) 

5081 # No explicit output 

5082 if out is None: 

5083 result = self.filled(0).sum(axis, dtype=dtype, **kwargs) 

5084 rndim = getattr(result, 'ndim', 0) 

5085 if rndim: 

5086 result = result.view(type(self)) 

5087 result.__setmask__(newmask) 

5088 elif newmask: 

5089 result = masked 

5090 return result 

5091 # Explicit output 

5092 result = self.filled(0).sum(axis, dtype=dtype, out=out, **kwargs) 

5093 if isinstance(out, MaskedArray): 

5094 outmask = getmask(out) 

5095 if outmask is nomask: 

5096 outmask = out._mask = make_mask_none(out.shape) 

5097 outmask.flat = newmask 

5098 return out 

5099 

5100 def cumsum(self, axis=None, dtype=None, out=None): 

5101 """ 

5102 Return the cumulative sum of the array elements over the given axis. 

5103 

5104 Masked values are set to 0 internally during the computation. 

5105 However, their position is saved, and the result will be masked at 

5106 the same locations. 

5107 

5108 Refer to `numpy.cumsum` for full documentation. 

5109 

5110 Notes 

5111 ----- 

5112 The mask is lost if `out` is not a valid :class:`MaskedArray` ! 

5113 

5114 Arithmetic is modular when using integer types, and no error is 

5115 raised on overflow. 

5116 

5117 See Also 

5118 -------- 

5119 numpy.ndarray.cumsum : corresponding function for ndarrays 

5120 numpy.cumsum : equivalent function 

5121 

5122 Examples 

5123 -------- 

5124 >>> marr = np.ma.array(np.arange(10), mask=[0,0,0,1,1,1,0,0,0,0]) 

5125 >>> marr.cumsum() 

5126 masked_array(data=[0, 1, 3, --, --, --, 9, 16, 24, 33], 

5127 mask=[False, False, False, True, True, True, False, False, 

5128 False, False], 

5129 fill_value=999999) 

5130 

5131 """ 

5132 result = self.filled(0).cumsum(axis=axis, dtype=dtype, out=out) 

5133 if out is not None: 

5134 if isinstance(out, MaskedArray): 

5135 out.__setmask__(self.mask) 

5136 return out 

5137 result = result.view(type(self)) 

5138 result.__setmask__(self._mask) 

5139 return result 

5140 

5141 def prod(self, axis=None, dtype=None, out=None, keepdims=np._NoValue): 

5142 """ 

5143 Return the product of the array elements over the given axis. 

5144 

5145 Masked elements are set to 1 internally for computation. 

5146 

5147 Refer to `numpy.prod` for full documentation. 

5148 

5149 Notes 

5150 ----- 

5151 Arithmetic is modular when using integer types, and no error is raised 

5152 on overflow. 

5153 

5154 See Also 

5155 -------- 

5156 numpy.ndarray.prod : corresponding function for ndarrays 

5157 numpy.prod : equivalent function 

5158 """ 

5159 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

5160 

5161 _mask = self._mask 

5162 newmask = _check_mask_axis(_mask, axis, **kwargs) 

5163 # No explicit output 

5164 if out is None: 

5165 result = self.filled(1).prod(axis, dtype=dtype, **kwargs) 

5166 rndim = getattr(result, 'ndim', 0) 

5167 if rndim: 

5168 result = result.view(type(self)) 

5169 result.__setmask__(newmask) 

5170 elif newmask: 

5171 result = masked 

5172 return result 

5173 # Explicit output 

5174 result = self.filled(1).prod(axis, dtype=dtype, out=out, **kwargs) 

5175 if isinstance(out, MaskedArray): 

5176 outmask = getmask(out) 

5177 if outmask is nomask: 

5178 outmask = out._mask = make_mask_none(out.shape) 

5179 outmask.flat = newmask 

5180 return out 

5181 product = prod 

5182 

5183 def cumprod(self, axis=None, dtype=None, out=None): 

5184 """ 

5185 Return the cumulative product of the array elements over the given axis. 

5186 

5187 Masked values are set to 1 internally during the computation. 

5188 However, their position is saved, and the result will be masked at 

5189 the same locations. 

5190 

5191 Refer to `numpy.cumprod` for full documentation. 

5192 

5193 Notes 

5194 ----- 

5195 The mask is lost if `out` is not a valid MaskedArray ! 

5196 

5197 Arithmetic is modular when using integer types, and no error is 

5198 raised on overflow. 

5199 

5200 See Also 

5201 -------- 

5202 numpy.ndarray.cumprod : corresponding function for ndarrays 

5203 numpy.cumprod : equivalent function 

5204 """ 

5205 result = self.filled(1).cumprod(axis=axis, dtype=dtype, out=out) 

5206 if out is not None: 

5207 if isinstance(out, MaskedArray): 

5208 out.__setmask__(self._mask) 

5209 return out 

5210 result = result.view(type(self)) 

5211 result.__setmask__(self._mask) 

5212 return result 

5213 

5214 def mean(self, axis=None, dtype=None, out=None, keepdims=np._NoValue): 

5215 """ 

5216 Returns the average of the array elements along given axis. 

5217 

5218 Masked entries are ignored, and result elements which are not 

5219 finite will be masked. 

5220 

5221 Refer to `numpy.mean` for full documentation. 

5222 

5223 See Also 

5224 -------- 

5225 numpy.ndarray.mean : corresponding function for ndarrays 

5226 numpy.mean : Equivalent function 

5227 numpy.ma.average: Weighted average. 

5228 

5229 Examples 

5230 -------- 

5231 >>> a = np.ma.array([1,2,3], mask=[False, False, True]) 

5232 >>> a 

5233 masked_array(data=[1, 2, --], 

5234 mask=[False, False, True], 

5235 fill_value=999999) 

5236 >>> a.mean() 

5237 1.5 

5238 

5239 """ 

5240 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

5241 

5242 if self._mask is nomask: 

5243 result = super(MaskedArray, self).mean(axis=axis, 

5244 dtype=dtype, **kwargs)[()] 

5245 else: 

5246 dsum = self.sum(axis=axis, dtype=dtype, **kwargs) 

5247 cnt = self.count(axis=axis, **kwargs) 

5248 if cnt.shape == () and (cnt == 0): 

5249 result = masked 

5250 else: 

5251 result = dsum * 1. / cnt 

5252 if out is not None: 

5253 out.flat = result 

5254 if isinstance(out, MaskedArray): 

5255 outmask = getmask(out) 

5256 if outmask is nomask: 

5257 outmask = out._mask = make_mask_none(out.shape) 

5258 outmask.flat = getmask(result) 

5259 return out 

5260 return result 

5261 

5262 def anom(self, axis=None, dtype=None): 

5263 """ 

5264 Compute the anomalies (deviations from the arithmetic mean) 

5265 along the given axis. 

5266 

5267 Returns an array of anomalies, with the same shape as the input and 

5268 where the arithmetic mean is computed along the given axis. 

5269 

5270 Parameters 

5271 ---------- 

5272 axis : int, optional 

5273 Axis over which the anomalies are taken. 

5274 The default is to use the mean of the flattened array as reference. 

5275 dtype : dtype, optional 

5276 Type to use in computing the variance. For arrays of integer type 

5277 the default is float32; for arrays of float types it is the same as 

5278 the array type. 

5279 

5280 See Also 

5281 -------- 

5282 mean : Compute the mean of the array. 

5283 

5284 Examples 

5285 -------- 

5286 >>> a = np.ma.array([1,2,3]) 

5287 >>> a.anom() 

5288 masked_array(data=[-1., 0., 1.], 

5289 mask=False, 

5290 fill_value=1e+20) 

5291 

5292 """ 

5293 m = self.mean(axis, dtype) 

5294 if m is masked: 

5295 return m 

5296 

5297 if not axis: 

5298 return self - m 

5299 else: 

5300 return self - expand_dims(m, axis) 

5301 

5302 def var(self, axis=None, dtype=None, out=None, ddof=0, 

5303 keepdims=np._NoValue): 

5304 """ 

5305 Returns the variance of the array elements along given axis. 

5306 

5307 Masked entries are ignored, and result elements which are not 

5308 finite will be masked. 

5309 

5310 Refer to `numpy.var` for full documentation. 

5311 

5312 See Also 

5313 -------- 

5314 numpy.ndarray.var : corresponding function for ndarrays 

5315 numpy.var : Equivalent function 

5316 """ 

5317 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

5318 

5319 # Easy case: nomask, business as usual 

5320 if self._mask is nomask: 

5321 ret = super(MaskedArray, self).var(axis=axis, dtype=dtype, out=out, 

5322 ddof=ddof, **kwargs)[()] 

5323 if out is not None: 

5324 if isinstance(out, MaskedArray): 

5325 out.__setmask__(nomask) 

5326 return out 

5327 return ret 

5328 

5329 # Some data are masked, yay! 

5330 cnt = self.count(axis=axis, **kwargs) - ddof 

5331 danom = self - self.mean(axis, dtype, keepdims=True) 

5332 if iscomplexobj(self): 

5333 danom = umath.absolute(danom) ** 2 

5334 else: 

5335 danom *= danom 

5336 dvar = divide(danom.sum(axis, **kwargs), cnt).view(type(self)) 

5337 # Apply the mask if it's not a scalar 

5338 if dvar.ndim: 

5339 dvar._mask = mask_or(self._mask.all(axis, **kwargs), (cnt <= 0)) 

5340 dvar._update_from(self) 

5341 elif getmask(dvar): 

5342 # Make sure that masked is returned when the scalar is masked. 

5343 dvar = masked 

5344 if out is not None: 

5345 if isinstance(out, MaskedArray): 

5346 out.flat = 0 

5347 out.__setmask__(True) 

5348 elif out.dtype.kind in 'biu': 

5349 errmsg = "Masked data information would be lost in one or "\ 

5350 "more location." 

5351 raise MaskError(errmsg) 

5352 else: 

5353 out.flat = np.nan 

5354 return out 

5355 # In case with have an explicit output 

5356 if out is not None: 

5357 # Set the data 

5358 out.flat = dvar 

5359 # Set the mask if needed 

5360 if isinstance(out, MaskedArray): 

5361 out.__setmask__(dvar.mask) 

5362 return out 

5363 return dvar 

5364 var.__doc__ = np.var.__doc__ 

5365 

5366 def std(self, axis=None, dtype=None, out=None, ddof=0, 

5367 keepdims=np._NoValue): 

5368 """ 

5369 Returns the standard deviation of the array elements along given axis. 

5370 

5371 Masked entries are ignored. 

5372 

5373 Refer to `numpy.std` for full documentation. 

5374 

5375 See Also 

5376 -------- 

5377 numpy.ndarray.std : corresponding function for ndarrays 

5378 numpy.std : Equivalent function 

5379 """ 

5380 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

5381 

5382 dvar = self.var(axis, dtype, out, ddof, **kwargs) 

5383 if dvar is not masked: 

5384 if out is not None: 

5385 np.power(out, 0.5, out=out, casting='unsafe') 

5386 return out 

5387 dvar = sqrt(dvar) 

5388 return dvar 

5389 

5390 def round(self, decimals=0, out=None): 

5391 """ 

5392 Return each element rounded to the given number of decimals. 

5393 

5394 Refer to `numpy.around` for full documentation. 

5395 

5396 See Also 

5397 -------- 

5398 numpy.ndarray.around : corresponding function for ndarrays 

5399 numpy.around : equivalent function 

5400 """ 

5401 result = self._data.round(decimals=decimals, out=out).view(type(self)) 

5402 if result.ndim > 0: 

5403 result._mask = self._mask 

5404 result._update_from(self) 

5405 elif self._mask: 

5406 # Return masked when the scalar is masked 

5407 result = masked 

5408 # No explicit output: we're done 

5409 if out is None: 

5410 return result 

5411 if isinstance(out, MaskedArray): 

5412 out.__setmask__(self._mask) 

5413 return out 

5414 

5415 def argsort(self, axis=np._NoValue, kind=None, order=None, 

5416 endwith=True, fill_value=None): 

5417 """ 

5418 Return an ndarray of indices that sort the array along the 

5419 specified axis. Masked values are filled beforehand to 

5420 `fill_value`. 

5421 

5422 Parameters 

5423 ---------- 

5424 axis : int, optional 

5425 Axis along which to sort. If None, the default, the flattened array 

5426 is used. 

5427 

5428 .. versionchanged:: 1.13.0 

5429 Previously, the default was documented to be -1, but that was 

5430 in error. At some future date, the default will change to -1, as 

5431 originally intended. 

5432 Until then, the axis should be given explicitly when 

5433 ``arr.ndim > 1``, to avoid a FutureWarning. 

5434 kind : {'quicksort', 'mergesort', 'heapsort', 'stable'}, optional 

5435 The sorting algorithm used. 

5436 order : list, optional 

5437 When `a` is an array with fields defined, this argument specifies 

5438 which fields to compare first, second, etc. Not all fields need be 

5439 specified. 

5440 endwith : {True, False}, optional 

5441 Whether missing values (if any) should be treated as the largest values 

5442 (True) or the smallest values (False) 

5443 When the array contains unmasked values at the same extremes of the 

5444 datatype, the ordering of these values and the masked values is 

5445 undefined. 

5446 fill_value : {var}, optional 

5447 Value used internally for the masked values. 

5448 If ``fill_value`` is not None, it supersedes ``endwith``. 

5449 

5450 Returns 

5451 ------- 

5452 index_array : ndarray, int 

5453 Array of indices that sort `a` along the specified axis. 

5454 In other words, ``a[index_array]`` yields a sorted `a`. 

5455 

5456 See Also 

5457 -------- 

5458 MaskedArray.sort : Describes sorting algorithms used. 

5459 lexsort : Indirect stable sort with multiple keys. 

5460 numpy.ndarray.sort : Inplace sort. 

5461 

5462 Notes 

5463 ----- 

5464 See `sort` for notes on the different sorting algorithms. 

5465 

5466 Examples 

5467 -------- 

5468 >>> a = np.ma.array([3,2,1], mask=[False, False, True]) 

5469 >>> a 

5470 masked_array(data=[3, 2, --], 

5471 mask=[False, False, True], 

5472 fill_value=999999) 

5473 >>> a.argsort() 

5474 array([1, 0, 2]) 

5475 

5476 """ 

5477 

5478 # 2017-04-11, Numpy 1.13.0, gh-8701: warn on axis default 

5479 if axis is np._NoValue: 

5480 axis = _deprecate_argsort_axis(self) 

5481 

5482 if fill_value is None: 

5483 if endwith: 

5484 # nan > inf 

5485 if np.issubdtype(self.dtype, np.floating): 

5486 fill_value = np.nan 

5487 else: 

5488 fill_value = minimum_fill_value(self) 

5489 else: 

5490 fill_value = maximum_fill_value(self) 

5491 

5492 filled = self.filled(fill_value) 

5493 return filled.argsort(axis=axis, kind=kind, order=order) 

5494 

5495 def argmin(self, axis=None, fill_value=None, out=None): 

5496 """ 

5497 Return array of indices to the minimum values along the given axis. 

5498 

5499 Parameters 

5500 ---------- 

5501 axis : {None, integer} 

5502 If None, the index is into the flattened array, otherwise along 

5503 the specified axis 

5504 fill_value : {var}, optional 

5505 Value used to fill in the masked values. If None, the output of 

5506 minimum_fill_value(self._data) is used instead. 

5507 out : {None, array}, optional 

5508 Array into which the result can be placed. Its type is preserved 

5509 and it must be of the right shape to hold the output. 

5510 

5511 Returns 

5512 ------- 

5513 ndarray or scalar 

5514 If multi-dimension input, returns a new ndarray of indices to the 

5515 minimum values along the given axis. Otherwise, returns a scalar 

5516 of index to the minimum values along the given axis. 

5517 

5518 Examples 

5519 -------- 

5520 >>> x = np.ma.array(np.arange(4), mask=[1,1,0,0]) 

5521 >>> x.shape = (2,2) 

5522 >>> x 

5523 masked_array( 

5524 data=[[--, --], 

5525 [2, 3]], 

5526 mask=[[ True, True], 

5527 [False, False]], 

5528 fill_value=999999) 

5529 >>> x.argmin(axis=0, fill_value=-1) 

5530 array([0, 0]) 

5531 >>> x.argmin(axis=0, fill_value=9) 

5532 array([1, 1]) 

5533 

5534 """ 

5535 if fill_value is None: 

5536 fill_value = minimum_fill_value(self) 

5537 d = self.filled(fill_value).view(ndarray) 

5538 return d.argmin(axis, out=out) 

5539 

5540 def argmax(self, axis=None, fill_value=None, out=None): 

5541 """ 

5542 Returns array of indices of the maximum values along the given axis. 

5543 Masked values are treated as if they had the value fill_value. 

5544 

5545 Parameters 

5546 ---------- 

5547 axis : {None, integer} 

5548 If None, the index is into the flattened array, otherwise along 

5549 the specified axis 

5550 fill_value : {var}, optional 

5551 Value used to fill in the masked values. If None, the output of 

5552 maximum_fill_value(self._data) is used instead. 

5553 out : {None, array}, optional 

5554 Array into which the result can be placed. Its type is preserved 

5555 and it must be of the right shape to hold the output. 

5556 

5557 Returns 

5558 ------- 

5559 index_array : {integer_array} 

5560 

5561 Examples 

5562 -------- 

5563 >>> a = np.arange(6).reshape(2,3) 

5564 >>> a.argmax() 

5565 5 

5566 >>> a.argmax(0) 

5567 array([1, 1, 1]) 

5568 >>> a.argmax(1) 

5569 array([2, 2]) 

5570 

5571 """ 

5572 if fill_value is None: 

5573 fill_value = maximum_fill_value(self._data) 

5574 d = self.filled(fill_value).view(ndarray) 

5575 return d.argmax(axis, out=out) 

5576 

5577 def sort(self, axis=-1, kind=None, order=None, 

5578 endwith=True, fill_value=None): 

5579 """ 

5580 Sort the array, in-place 

5581 

5582 Parameters 

5583 ---------- 

5584 a : array_like 

5585 Array to be sorted. 

5586 axis : int, optional 

5587 Axis along which to sort. If None, the array is flattened before 

5588 sorting. The default is -1, which sorts along the last axis. 

5589 kind : {'quicksort', 'mergesort', 'heapsort', 'stable'}, optional 

5590 The sorting algorithm used. 

5591 order : list, optional 

5592 When `a` is a structured array, this argument specifies which fields 

5593 to compare first, second, and so on. This list does not need to 

5594 include all of the fields. 

5595 endwith : {True, False}, optional 

5596 Whether missing values (if any) should be treated as the largest values 

5597 (True) or the smallest values (False) 

5598 When the array contains unmasked values sorting at the same extremes of the 

5599 datatype, the ordering of these values and the masked values is 

5600 undefined. 

5601 fill_value : {var}, optional 

5602 Value used internally for the masked values. 

5603 If ``fill_value`` is not None, it supersedes ``endwith``. 

5604 

5605 Returns 

5606 ------- 

5607 sorted_array : ndarray 

5608 Array of the same type and shape as `a`. 

5609 

5610 See Also 

5611 -------- 

5612 numpy.ndarray.sort : Method to sort an array in-place. 

5613 argsort : Indirect sort. 

5614 lexsort : Indirect stable sort on multiple keys. 

5615 searchsorted : Find elements in a sorted array. 

5616 

5617 Notes 

5618 ----- 

5619 See ``sort`` for notes on the different sorting algorithms. 

5620 

5621 Examples 

5622 -------- 

5623 >>> a = np.ma.array([1, 2, 5, 4, 3],mask=[0, 1, 0, 1, 0]) 

5624 >>> # Default 

5625 >>> a.sort() 

5626 >>> a 

5627 masked_array(data=[1, 3, 5, --, --], 

5628 mask=[False, False, False, True, True], 

5629 fill_value=999999) 

5630 

5631 >>> a = np.ma.array([1, 2, 5, 4, 3],mask=[0, 1, 0, 1, 0]) 

5632 >>> # Put missing values in the front 

5633 >>> a.sort(endwith=False) 

5634 >>> a 

5635 masked_array(data=[--, --, 1, 3, 5], 

5636 mask=[ True, True, False, False, False], 

5637 fill_value=999999) 

5638 

5639 >>> a = np.ma.array([1, 2, 5, 4, 3],mask=[0, 1, 0, 1, 0]) 

5640 >>> # fill_value takes over endwith 

5641 >>> a.sort(endwith=False, fill_value=3) 

5642 >>> a 

5643 masked_array(data=[1, --, --, 3, 5], 

5644 mask=[False, True, True, False, False], 

5645 fill_value=999999) 

5646 

5647 """ 

5648 if self._mask is nomask: 

5649 ndarray.sort(self, axis=axis, kind=kind, order=order) 

5650 return 

5651 

5652 if self is masked: 

5653 return 

5654 

5655 sidx = self.argsort(axis=axis, kind=kind, order=order, 

5656 fill_value=fill_value, endwith=endwith) 

5657 

5658 self[...] = np.take_along_axis(self, sidx, axis=axis) 

5659 

5660 def min(self, axis=None, out=None, fill_value=None, keepdims=np._NoValue): 

5661 """ 

5662 Return the minimum along a given axis. 

5663 

5664 Parameters 

5665 ---------- 

5666 axis : {None, int}, optional 

5667 Axis along which to operate. By default, ``axis`` is None and the 

5668 flattened input is used. 

5669 out : array_like, optional 

5670 Alternative output array in which to place the result. Must be of 

5671 the same shape and buffer length as the expected output. 

5672 fill_value : {var}, optional 

5673 Value used to fill in the masked values. 

5674 If None, use the output of `minimum_fill_value`. 

5675 keepdims : bool, optional 

5676 If this is set to True, the axes which are reduced are left 

5677 in the result as dimensions with size one. With this option, 

5678 the result will broadcast correctly against the array. 

5679 

5680 Returns 

5681 ------- 

5682 amin : array_like 

5683 New array holding the result. 

5684 If ``out`` was specified, ``out`` is returned. 

5685 

5686 See Also 

5687 -------- 

5688 minimum_fill_value 

5689 Returns the minimum filling value for a given datatype. 

5690 

5691 """ 

5692 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

5693 

5694 _mask = self._mask 

5695 newmask = _check_mask_axis(_mask, axis, **kwargs) 

5696 if fill_value is None: 

5697 fill_value = minimum_fill_value(self) 

5698 # No explicit output 

5699 if out is None: 

5700 result = self.filled(fill_value).min( 

5701 axis=axis, out=out, **kwargs).view(type(self)) 

5702 if result.ndim: 

5703 # Set the mask 

5704 result.__setmask__(newmask) 

5705 # Get rid of Infs 

5706 if newmask.ndim: 

5707 np.copyto(result, result.fill_value, where=newmask) 

5708 elif newmask: 

5709 result = masked 

5710 return result 

5711 # Explicit output 

5712 result = self.filled(fill_value).min(axis=axis, out=out, **kwargs) 

5713 if isinstance(out, MaskedArray): 

5714 outmask = getmask(out) 

5715 if outmask is nomask: 

5716 outmask = out._mask = make_mask_none(out.shape) 

5717 outmask.flat = newmask 

5718 else: 

5719 if out.dtype.kind in 'biu': 

5720 errmsg = "Masked data information would be lost in one or more"\ 

5721 " location." 

5722 raise MaskError(errmsg) 

5723 np.copyto(out, np.nan, where=newmask) 

5724 return out 

5725 

5726 # unique to masked arrays 

5727 def mini(self, axis=None): 

5728 """ 

5729 Return the array minimum along the specified axis. 

5730 

5731 .. deprecated:: 1.13.0 

5732 This function is identical to both: 

5733 

5734 * ``self.min(keepdims=True, axis=axis).squeeze(axis=axis)`` 

5735 * ``np.ma.minimum.reduce(self, axis=axis)`` 

5736 

5737 Typically though, ``self.min(axis=axis)`` is sufficient. 

5738 

5739 Parameters 

5740 ---------- 

5741 axis : int, optional 

5742 The axis along which to find the minima. Default is None, in which case 

5743 the minimum value in the whole array is returned. 

5744 

5745 Returns 

5746 ------- 

5747 min : scalar or MaskedArray 

5748 If `axis` is None, the result is a scalar. Otherwise, if `axis` is 

5749 given and the array is at least 2-D, the result is a masked array with 

5750 dimension one smaller than the array on which `mini` is called. 

5751 

5752 Examples 

5753 -------- 

5754 >>> x = np.ma.array(np.arange(6), mask=[0 ,1, 0, 0, 0 ,1]).reshape(3, 2) 

5755 >>> x 

5756 masked_array( 

5757 data=[[0, --], 

5758 [2, 3], 

5759 [4, --]], 

5760 mask=[[False, True], 

5761 [False, False], 

5762 [False, True]], 

5763 fill_value=999999) 

5764 >>> x.mini() 

5765 masked_array(data=0, 

5766 mask=False, 

5767 fill_value=999999) 

5768 >>> x.mini(axis=0) 

5769 masked_array(data=[0, 3], 

5770 mask=[False, False], 

5771 fill_value=999999) 

5772 >>> x.mini(axis=1) 

5773 masked_array(data=[0, 2, 4], 

5774 mask=[False, False, False], 

5775 fill_value=999999) 

5776 

5777 There is a small difference between `mini` and `min`: 

5778 

5779 >>> x[:,1].mini(axis=0) 

5780 masked_array(data=3, 

5781 mask=False, 

5782 fill_value=999999) 

5783 >>> x[:,1].min(axis=0) 

5784 3 

5785 """ 

5786 

5787 # 2016-04-13, 1.13.0, gh-8764 

5788 warnings.warn( 

5789 "`mini` is deprecated; use the `min` method or " 

5790 "`np.ma.minimum.reduce instead.", 

5791 DeprecationWarning, stacklevel=2) 

5792 return minimum.reduce(self, axis) 

5793 

5794 def max(self, axis=None, out=None, fill_value=None, keepdims=np._NoValue): 

5795 """ 

5796 Return the maximum along a given axis. 

5797 

5798 Parameters 

5799 ---------- 

5800 axis : {None, int}, optional 

5801 Axis along which to operate. By default, ``axis`` is None and the 

5802 flattened input is used. 

5803 out : array_like, optional 

5804 Alternative output array in which to place the result. Must 

5805 be of the same shape and buffer length as the expected output. 

5806 fill_value : {var}, optional 

5807 Value used to fill in the masked values. 

5808 If None, use the output of maximum_fill_value(). 

5809 keepdims : bool, optional 

5810 If this is set to True, the axes which are reduced are left 

5811 in the result as dimensions with size one. With this option, 

5812 the result will broadcast correctly against the array. 

5813 

5814 Returns 

5815 ------- 

5816 amax : array_like 

5817 New array holding the result. 

5818 If ``out`` was specified, ``out`` is returned. 

5819 

5820 See Also 

5821 -------- 

5822 maximum_fill_value 

5823 Returns the maximum filling value for a given datatype. 

5824 

5825 """ 

5826 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

5827 

5828 _mask = self._mask 

5829 newmask = _check_mask_axis(_mask, axis, **kwargs) 

5830 if fill_value is None: 

5831 fill_value = maximum_fill_value(self) 

5832 # No explicit output 

5833 if out is None: 

5834 result = self.filled(fill_value).max( 

5835 axis=axis, out=out, **kwargs).view(type(self)) 

5836 if result.ndim: 

5837 # Set the mask 

5838 result.__setmask__(newmask) 

5839 # Get rid of Infs 

5840 if newmask.ndim: 

5841 np.copyto(result, result.fill_value, where=newmask) 

5842 elif newmask: 

5843 result = masked 

5844 return result 

5845 # Explicit output 

5846 result = self.filled(fill_value).max(axis=axis, out=out, **kwargs) 

5847 if isinstance(out, MaskedArray): 

5848 outmask = getmask(out) 

5849 if outmask is nomask: 

5850 outmask = out._mask = make_mask_none(out.shape) 

5851 outmask.flat = newmask 

5852 else: 

5853 

5854 if out.dtype.kind in 'biu': 

5855 errmsg = "Masked data information would be lost in one or more"\ 

5856 " location." 

5857 raise MaskError(errmsg) 

5858 np.copyto(out, np.nan, where=newmask) 

5859 return out 

5860 

5861 def ptp(self, axis=None, out=None, fill_value=None, keepdims=False): 

5862 """ 

5863 Return (maximum - minimum) along the given dimension 

5864 (i.e. peak-to-peak value). 

5865 

5866 .. warning:: 

5867 `ptp` preserves the data type of the array. This means the 

5868 return value for an input of signed integers with n bits 

5869 (e.g. `np.int8`, `np.int16`, etc) is also a signed integer 

5870 with n bits. In that case, peak-to-peak values greater than 

5871 ``2**(n-1)-1`` will be returned as negative values. An example 

5872 with a work-around is shown below. 

5873 

5874 Parameters 

5875 ---------- 

5876 axis : {None, int}, optional 

5877 Axis along which to find the peaks. If None (default) the 

5878 flattened array is used. 

5879 out : {None, array_like}, optional 

5880 Alternative output array in which to place the result. It must 

5881 have the same shape and buffer length as the expected output 

5882 but the type will be cast if necessary. 

5883 fill_value : {var}, optional 

5884 Value used to fill in the masked values. 

5885 keepdims : bool, optional 

5886 If this is set to True, the axes which are reduced are left 

5887 in the result as dimensions with size one. With this option, 

5888 the result will broadcast correctly against the array. 

5889 

5890 Returns 

5891 ------- 

5892 ptp : ndarray. 

5893 A new array holding the result, unless ``out`` was 

5894 specified, in which case a reference to ``out`` is returned. 

5895 

5896 Examples 

5897 -------- 

5898 >>> x = np.ma.MaskedArray([[4, 9, 2, 10], 

5899 ... [6, 9, 7, 12]]) 

5900 

5901 >>> x.ptp(axis=1) 

5902 masked_array(data=[8, 6], 

5903 mask=False, 

5904 fill_value=999999) 

5905 

5906 >>> x.ptp(axis=0) 

5907 masked_array(data=[2, 0, 5, 2], 

5908 mask=False, 

5909 fill_value=999999) 

5910 

5911 >>> x.ptp() 

5912 10 

5913 

5914 This example shows that a negative value can be returned when 

5915 the input is an array of signed integers. 

5916 

5917 >>> y = np.ma.MaskedArray([[1, 127], 

5918 ... [0, 127], 

5919 ... [-1, 127], 

5920 ... [-2, 127]], dtype=np.int8) 

5921 >>> y.ptp(axis=1) 

5922 masked_array(data=[ 126, 127, -128, -127], 

5923 mask=False, 

5924 fill_value=999999, 

5925 dtype=int8) 

5926 

5927 A work-around is to use the `view()` method to view the result as 

5928 unsigned integers with the same bit width: 

5929 

5930 >>> y.ptp(axis=1).view(np.uint8) 

5931 masked_array(data=[126, 127, 128, 129], 

5932 mask=False, 

5933 fill_value=999999, 

5934 dtype=uint8) 

5935 """ 

5936 if out is None: 

5937 result = self.max(axis=axis, fill_value=fill_value, 

5938 keepdims=keepdims) 

5939 result -= self.min(axis=axis, fill_value=fill_value, 

5940 keepdims=keepdims) 

5941 return result 

5942 out.flat = self.max(axis=axis, out=out, fill_value=fill_value, 

5943 keepdims=keepdims) 

5944 min_value = self.min(axis=axis, fill_value=fill_value, 

5945 keepdims=keepdims) 

5946 np.subtract(out, min_value, out=out, casting='unsafe') 

5947 return out 

5948 

5949 def partition(self, *args, **kwargs): 

5950 warnings.warn("Warning: 'partition' will ignore the 'mask' " 

5951 f"of the {self.__class__.__name__}.", 

5952 stacklevel=2) 

5953 return super(MaskedArray, self).partition(*args, **kwargs) 

5954 

5955 def argpartition(self, *args, **kwargs): 

5956 warnings.warn("Warning: 'argpartition' will ignore the 'mask' " 

5957 f"of the {self.__class__.__name__}.", 

5958 stacklevel=2) 

5959 return super(MaskedArray, self).argpartition(*args, **kwargs) 

5960 

5961 def take(self, indices, axis=None, out=None, mode='raise'): 

5962 """ 

5963 """ 

5964 (_data, _mask) = (self._data, self._mask) 

5965 cls = type(self) 

5966 # Make sure the indices are not masked 

5967 maskindices = getmask(indices) 

5968 if maskindices is not nomask: 

5969 indices = indices.filled(0) 

5970 # Get the data, promoting scalars to 0d arrays with [...] so that 

5971 # .view works correctly 

5972 if out is None: 

5973 out = _data.take(indices, axis=axis, mode=mode)[...].view(cls) 

5974 else: 

5975 np.take(_data, indices, axis=axis, mode=mode, out=out) 

5976 # Get the mask 

5977 if isinstance(out, MaskedArray): 

5978 if _mask is nomask: 

5979 outmask = maskindices 

5980 else: 

5981 outmask = _mask.take(indices, axis=axis, mode=mode) 

5982 outmask |= maskindices 

5983 out.__setmask__(outmask) 

5984 # demote 0d arrays back to scalars, for consistency with ndarray.take 

5985 return out[()] 

5986 

5987 # Array methods 

5988 copy = _arraymethod('copy') 

5989 diagonal = _arraymethod('diagonal') 

5990 flatten = _arraymethod('flatten') 

5991 repeat = _arraymethod('repeat') 

5992 squeeze = _arraymethod('squeeze') 

5993 swapaxes = _arraymethod('swapaxes') 

5994 T = property(fget=lambda self: self.transpose()) 

5995 transpose = _arraymethod('transpose') 

5996 

5997 def tolist(self, fill_value=None): 

5998 """ 

5999 Return the data portion of the masked array as a hierarchical Python list. 

6000 

6001 Data items are converted to the nearest compatible Python type. 

6002 Masked values are converted to `fill_value`. If `fill_value` is None, 

6003 the corresponding entries in the output list will be ``None``. 

6004 

6005 Parameters 

6006 ---------- 

6007 fill_value : scalar, optional 

6008 The value to use for invalid entries. Default is None. 

6009 

6010 Returns 

6011 ------- 

6012 result : list 

6013 The Python list representation of the masked array. 

6014 

6015 Examples 

6016 -------- 

6017 >>> x = np.ma.array([[1,2,3], [4,5,6], [7,8,9]], mask=[0] + [1,0]*4) 

6018 >>> x.tolist() 

6019 [[1, None, 3], [None, 5, None], [7, None, 9]] 

6020 >>> x.tolist(-999) 

6021 [[1, -999, 3], [-999, 5, -999], [7, -999, 9]] 

6022 

6023 """ 

6024 _mask = self._mask 

6025 # No mask ? Just return .data.tolist ? 

6026 if _mask is nomask: 

6027 return self._data.tolist() 

6028 # Explicit fill_value: fill the array and get the list 

6029 if fill_value is not None: 

6030 return self.filled(fill_value).tolist() 

6031 # Structured array. 

6032 names = self.dtype.names 

6033 if names: 

6034 result = self._data.astype([(_, object) for _ in names]) 

6035 for n in names: 

6036 result[n][_mask[n]] = None 

6037 return result.tolist() 

6038 # Standard arrays. 

6039 if _mask is nomask: 

6040 return [None] 

6041 # Set temps to save time when dealing w/ marrays. 

6042 inishape = self.shape 

6043 result = np.array(self._data.ravel(), dtype=object) 

6044 result[_mask.ravel()] = None 

6045 result.shape = inishape 

6046 return result.tolist() 

6047 

6048 def tostring(self, fill_value=None, order='C'): 

6049 r""" 

6050 A compatibility alias for `tobytes`, with exactly the same behavior. 

6051 

6052 Despite its name, it returns `bytes` not `str`\ s. 

6053 

6054 .. deprecated:: 1.19.0 

6055 """ 

6056 # 2020-03-30, Numpy 1.19.0 

6057 warnings.warn( 

6058 "tostring() is deprecated. Use tobytes() instead.", 

6059 DeprecationWarning, stacklevel=2) 

6060 

6061 return self.tobytes(fill_value, order=order) 

6062 

6063 def tobytes(self, fill_value=None, order='C'): 

6064 """ 

6065 Return the array data as a string containing the raw bytes in the array. 

6066 

6067 The array is filled with a fill value before the string conversion. 

6068 

6069 .. versionadded:: 1.9.0 

6070 

6071 Parameters 

6072 ---------- 

6073 fill_value : scalar, optional 

6074 Value used to fill in the masked values. Default is None, in which 

6075 case `MaskedArray.fill_value` is used. 

6076 order : {'C','F','A'}, optional 

6077 Order of the data item in the copy. Default is 'C'. 

6078 

6079 - 'C' -- C order (row major). 

6080 - 'F' -- Fortran order (column major). 

6081 - 'A' -- Any, current order of array. 

6082 - None -- Same as 'A'. 

6083 

6084 See Also 

6085 -------- 

6086 numpy.ndarray.tobytes 

6087 tolist, tofile 

6088 

6089 Notes 

6090 ----- 

6091 As for `ndarray.tobytes`, information about the shape, dtype, etc., 

6092 but also about `fill_value`, will be lost. 

6093 

6094 Examples 

6095 -------- 

6096 >>> x = np.ma.array(np.array([[1, 2], [3, 4]]), mask=[[0, 1], [1, 0]]) 

6097 >>> x.tobytes() 

6098 b'\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00?B\\x0f\\x00\\x00\\x00\\x00\\x00?B\\x0f\\x00\\x00\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00' 

6099 

6100 """ 

6101 return self.filled(fill_value).tobytes(order=order) 

6102 

6103 def tofile(self, fid, sep="", format="%s"): 

6104 """ 

6105 Save a masked array to a file in binary format. 

6106 

6107 .. warning:: 

6108 This function is not implemented yet. 

6109 

6110 Raises 

6111 ------ 

6112 NotImplementedError 

6113 When `tofile` is called. 

6114 

6115 """ 

6116 raise NotImplementedError("MaskedArray.tofile() not implemented yet.") 

6117 

6118 def toflex(self): 

6119 """ 

6120 Transforms a masked array into a flexible-type array. 

6121 

6122 The flexible type array that is returned will have two fields: 

6123 

6124 * the ``_data`` field stores the ``_data`` part of the array. 

6125 * the ``_mask`` field stores the ``_mask`` part of the array. 

6126 

6127 Parameters 

6128 ---------- 

6129 None 

6130 

6131 Returns 

6132 ------- 

6133 record : ndarray 

6134 A new flexible-type `ndarray` with two fields: the first element 

6135 containing a value, the second element containing the corresponding 

6136 mask boolean. The returned record shape matches self.shape. 

6137 

6138 Notes 

6139 ----- 

6140 A side-effect of transforming a masked array into a flexible `ndarray` is 

6141 that meta information (``fill_value``, ...) will be lost. 

6142 

6143 Examples 

6144 -------- 

6145 >>> x = np.ma.array([[1,2,3],[4,5,6],[7,8,9]], mask=[0] + [1,0]*4) 

6146 >>> x 

6147 masked_array( 

6148 data=[[1, --, 3], 

6149 [--, 5, --], 

6150 [7, --, 9]], 

6151 mask=[[False, True, False], 

6152 [ True, False, True], 

6153 [False, True, False]], 

6154 fill_value=999999) 

6155 >>> x.toflex() 

6156 array([[(1, False), (2, True), (3, False)], 

6157 [(4, True), (5, False), (6, True)], 

6158 [(7, False), (8, True), (9, False)]], 

6159 dtype=[('_data', '<i8'), ('_mask', '?')]) 

6160 

6161 """ 

6162 # Get the basic dtype. 

6163 ddtype = self.dtype 

6164 # Make sure we have a mask 

6165 _mask = self._mask 

6166 if _mask is None: 

6167 _mask = make_mask_none(self.shape, ddtype) 

6168 # And get its dtype 

6169 mdtype = self._mask.dtype 

6170 

6171 record = np.ndarray(shape=self.shape, 

6172 dtype=[('_data', ddtype), ('_mask', mdtype)]) 

6173 record['_data'] = self._data 

6174 record['_mask'] = self._mask 

6175 return record 

6176 torecords = toflex 

6177 

6178 # Pickling 

6179 def __getstate__(self): 

6180 """Return the internal state of the masked array, for pickling 

6181 purposes. 

6182 

6183 """ 

6184 cf = 'CF'[self.flags.fnc] 

6185 data_state = super(MaskedArray, self).__reduce__()[2] 

6186 return data_state + (getmaskarray(self).tobytes(cf), self._fill_value) 

6187 

6188 def __setstate__(self, state): 

6189 """Restore the internal state of the masked array, for 

6190 pickling purposes. ``state`` is typically the output of the 

6191 ``__getstate__`` output, and is a 5-tuple: 

6192 

6193 - class name 

6194 - a tuple giving the shape of the data 

6195 - a typecode for the data 

6196 - a binary string for the data 

6197 - a binary string for the mask. 

6198 

6199 """ 

6200 (_, shp, typ, isf, raw, msk, flv) = state 

6201 super(MaskedArray, self).__setstate__((shp, typ, isf, raw)) 

6202 self._mask.__setstate__((shp, make_mask_descr(typ), isf, msk)) 

6203 self.fill_value = flv 

6204 

6205 def __reduce__(self): 

6206 """Return a 3-tuple for pickling a MaskedArray. 

6207 

6208 """ 

6209 return (_mareconstruct, 

6210 (self.__class__, self._baseclass, (0,), 'b',), 

6211 self.__getstate__()) 

6212 

6213 def __deepcopy__(self, memo=None): 

6214 from copy import deepcopy 

6215 copied = MaskedArray.__new__(type(self), self, copy=True) 

6216 if memo is None: 

6217 memo = {} 

6218 memo[id(self)] = copied 

6219 for (k, v) in self.__dict__.items(): 

6220 copied.__dict__[k] = deepcopy(v, memo) 

6221 return copied 

6222 

6223 

6224def _mareconstruct(subtype, baseclass, baseshape, basetype,): 

6225 """Internal function that builds a new MaskedArray from the 

6226 information stored in a pickle. 

6227 

6228 """ 

6229 _data = ndarray.__new__(baseclass, baseshape, basetype) 

6230 _mask = ndarray.__new__(ndarray, baseshape, make_mask_descr(basetype)) 

6231 return subtype.__new__(subtype, _data, mask=_mask, dtype=basetype,) 

6232 

6233 

6234class mvoid(MaskedArray): 

6235 """ 

6236 Fake a 'void' object to use for masked array with structured dtypes. 

6237 """ 

6238 

6239 def __new__(self, data, mask=nomask, dtype=None, fill_value=None, 

6240 hardmask=False, copy=False, subok=True): 

6241 _data = np.array(data, copy=copy, subok=subok, dtype=dtype) 

6242 _data = _data.view(self) 

6243 _data._hardmask = hardmask 

6244 if mask is not nomask: 

6245 if isinstance(mask, np.void): 

6246 _data._mask = mask 

6247 else: 

6248 try: 

6249 # Mask is already a 0D array 

6250 _data._mask = np.void(mask) 

6251 except TypeError: 

6252 # Transform the mask to a void 

6253 mdtype = make_mask_descr(dtype) 

6254 _data._mask = np.array(mask, dtype=mdtype)[()] 

6255 if fill_value is not None: 

6256 _data.fill_value = fill_value 

6257 return _data 

6258 

6259 @property 

6260 def _data(self): 

6261 # Make sure that the _data part is a np.void 

6262 return super(mvoid, self)._data[()] 

6263 

6264 def __getitem__(self, indx): 

6265 """ 

6266 Get the index. 

6267 

6268 """ 

6269 m = self._mask 

6270 if isinstance(m[indx], ndarray): 

6271 # Can happen when indx is a multi-dimensional field: 

6272 # A = ma.masked_array(data=[([0,1],)], mask=[([True, 

6273 # False],)], dtype=[("A", ">i2", (2,))]) 

6274 # x = A[0]; y = x["A"]; then y.mask["A"].size==2 

6275 # and we can not say masked/unmasked. 

6276 # The result is no longer mvoid! 

6277 # See also issue #6724. 

6278 return masked_array( 

6279 data=self._data[indx], mask=m[indx], 

6280 fill_value=self._fill_value[indx], 

6281 hard_mask=self._hardmask) 

6282 if m is not nomask and m[indx]: 

6283 return masked 

6284 return self._data[indx] 

6285 

6286 def __setitem__(self, indx, value): 

6287 self._data[indx] = value 

6288 if self._hardmask: 

6289 self._mask[indx] |= getattr(value, "_mask", False) 

6290 else: 

6291 self._mask[indx] = getattr(value, "_mask", False) 

6292 

6293 def __str__(self): 

6294 m = self._mask 

6295 if m is nomask: 

6296 return str(self._data) 

6297 

6298 rdtype = _replace_dtype_fields(self._data.dtype, "O") 

6299 data_arr = super(mvoid, self)._data 

6300 res = data_arr.astype(rdtype) 

6301 _recursive_printoption(res, self._mask, masked_print_option) 

6302 return str(res) 

6303 

6304 __repr__ = __str__ 

6305 

6306 def __iter__(self): 

6307 "Defines an iterator for mvoid" 

6308 (_data, _mask) = (self._data, self._mask) 

6309 if _mask is nomask: 

6310 yield from _data 

6311 else: 

6312 for (d, m) in zip(_data, _mask): 

6313 if m: 

6314 yield masked 

6315 else: 

6316 yield d 

6317 

6318 def __len__(self): 

6319 return self._data.__len__() 

6320 

6321 def filled(self, fill_value=None): 

6322 """ 

6323 Return a copy with masked fields filled with a given value. 

6324 

6325 Parameters 

6326 ---------- 

6327 fill_value : array_like, optional 

6328 The value to use for invalid entries. Can be scalar or 

6329 non-scalar. If latter is the case, the filled array should 

6330 be broadcastable over input array. Default is None, in 

6331 which case the `fill_value` attribute is used instead. 

6332 

6333 Returns 

6334 ------- 

6335 filled_void 

6336 A `np.void` object 

6337 

6338 See Also 

6339 -------- 

6340 MaskedArray.filled 

6341 

6342 """ 

6343 return asarray(self).filled(fill_value)[()] 

6344 

6345 def tolist(self): 

6346 """ 

6347 Transforms the mvoid object into a tuple. 

6348 

6349 Masked fields are replaced by None. 

6350 

6351 Returns 

6352 ------- 

6353 returned_tuple 

6354 Tuple of fields 

6355 """ 

6356 _mask = self._mask 

6357 if _mask is nomask: 

6358 return self._data.tolist() 

6359 result = [] 

6360 for (d, m) in zip(self._data, self._mask): 

6361 if m: 

6362 result.append(None) 

6363 else: 

6364 # .item() makes sure we return a standard Python object 

6365 result.append(d.item()) 

6366 return tuple(result) 

6367 

6368 

6369############################################################################## 

6370# Shortcuts # 

6371############################################################################## 

6372 

6373 

6374def isMaskedArray(x): 

6375 """ 

6376 Test whether input is an instance of MaskedArray. 

6377 

6378 This function returns True if `x` is an instance of MaskedArray 

6379 and returns False otherwise. Any object is accepted as input. 

6380 

6381 Parameters 

6382 ---------- 

6383 x : object 

6384 Object to test. 

6385 

6386 Returns 

6387 ------- 

6388 result : bool 

6389 True if `x` is a MaskedArray. 

6390 

6391 See Also 

6392 -------- 

6393 isMA : Alias to isMaskedArray. 

6394 isarray : Alias to isMaskedArray. 

6395 

6396 Examples 

6397 -------- 

6398 >>> import numpy.ma as ma 

6399 >>> a = np.eye(3, 3) 

6400 >>> a 

6401 array([[ 1., 0., 0.], 

6402 [ 0., 1., 0.], 

6403 [ 0., 0., 1.]]) 

6404 >>> m = ma.masked_values(a, 0) 

6405 >>> m 

6406 masked_array( 

6407 data=[[1.0, --, --], 

6408 [--, 1.0, --], 

6409 [--, --, 1.0]], 

6410 mask=[[False, True, True], 

6411 [ True, False, True], 

6412 [ True, True, False]], 

6413 fill_value=0.0) 

6414 >>> ma.isMaskedArray(a) 

6415 False 

6416 >>> ma.isMaskedArray(m) 

6417 True 

6418 >>> ma.isMaskedArray([0, 1, 2]) 

6419 False 

6420 

6421 """ 

6422 return isinstance(x, MaskedArray) 

6423 

6424 

6425isarray = isMaskedArray 

6426isMA = isMaskedArray # backward compatibility 

6427 

6428 

6429class MaskedConstant(MaskedArray): 

6430 # the lone np.ma.masked instance 

6431 __singleton = None 

6432 

6433 @classmethod 

6434 def __has_singleton(cls): 

6435 # second case ensures `cls.__singleton` is not just a view on the 

6436 # superclass singleton 

6437 return cls.__singleton is not None and type(cls.__singleton) is cls 

6438 

6439 def __new__(cls): 

6440 if not cls.__has_singleton(): 

6441 # We define the masked singleton as a float for higher precedence. 

6442 # Note that it can be tricky sometimes w/ type comparison 

6443 data = np.array(0.) 

6444 mask = np.array(True) 

6445 

6446 # prevent any modifications 

6447 data.flags.writeable = False 

6448 mask.flags.writeable = False 

6449 

6450 # don't fall back on MaskedArray.__new__(MaskedConstant), since 

6451 # that might confuse it - this way, the construction is entirely 

6452 # within our control 

6453 cls.__singleton = MaskedArray(data, mask=mask).view(cls) 

6454 

6455 return cls.__singleton 

6456 

6457 def __array_finalize__(self, obj): 

6458 if not self.__has_singleton(): 

6459 # this handles the `.view` in __new__, which we want to copy across 

6460 # properties normally 

6461 return super(MaskedConstant, self).__array_finalize__(obj) 

6462 elif self is self.__singleton: 

6463 # not clear how this can happen, play it safe 

6464 pass 

6465 else: 

6466 # everywhere else, we want to downcast to MaskedArray, to prevent a 

6467 # duplicate maskedconstant. 

6468 self.__class__ = MaskedArray 

6469 MaskedArray.__array_finalize__(self, obj) 

6470 

6471 def __array_prepare__(self, obj, context=None): 

6472 return self.view(MaskedArray).__array_prepare__(obj, context) 

6473 

6474 def __array_wrap__(self, obj, context=None): 

6475 return self.view(MaskedArray).__array_wrap__(obj, context) 

6476 

6477 def __str__(self): 

6478 return str(masked_print_option._display) 

6479 

6480 def __repr__(self): 

6481 if self is MaskedConstant.__singleton: 

6482 return 'masked' 

6483 else: 

6484 # it's a subclass, or something is wrong, make it obvious 

6485 return object.__repr__(self) 

6486 

6487 def __format__(self, format_spec): 

6488 # Replace ndarray.__format__ with the default, which supports no format characters. 

6489 # Supporting format characters is unwise here, because we do not know what type 

6490 # the user was expecting - better to not guess. 

6491 try: 

6492 return object.__format__(self, format_spec) 

6493 except TypeError: 

6494 # 2020-03-23, NumPy 1.19.0 

6495 warnings.warn( 

6496 "Format strings passed to MaskedConstant are ignored, but in future may " 

6497 "error or produce different behavior", 

6498 FutureWarning, stacklevel=2 

6499 ) 

6500 return object.__format__(self, "") 

6501 

6502 def __reduce__(self): 

6503 """Override of MaskedArray's __reduce__. 

6504 """ 

6505 return (self.__class__, ()) 

6506 

6507 # inplace operations have no effect. We have to override them to avoid 

6508 # trying to modify the readonly data and mask arrays 

6509 def __iop__(self, other): 

6510 return self 

6511 __iadd__ = \ 

6512 __isub__ = \ 

6513 __imul__ = \ 

6514 __ifloordiv__ = \ 

6515 __itruediv__ = \ 

6516 __ipow__ = \ 

6517 __iop__ 

6518 del __iop__ # don't leave this around 

6519 

6520 def copy(self, *args, **kwargs): 

6521 """ Copy is a no-op on the maskedconstant, as it is a scalar """ 

6522 # maskedconstant is a scalar, so copy doesn't need to copy. There's 

6523 # precedent for this with `np.bool_` scalars. 

6524 return self 

6525 

6526 def __copy__(self): 

6527 return self 

6528 

6529 def __deepcopy__(self, memo): 

6530 return self 

6531 

6532 def __setattr__(self, attr, value): 

6533 if not self.__has_singleton(): 

6534 # allow the singleton to be initialized 

6535 return super(MaskedConstant, self).__setattr__(attr, value) 

6536 elif self is self.__singleton: 

6537 raise AttributeError( 

6538 f"attributes of {self!r} are not writeable") 

6539 else: 

6540 # duplicate instance - we can end up here from __array_finalize__, 

6541 # where we set the __class__ attribute 

6542 return super(MaskedConstant, self).__setattr__(attr, value) 

6543 

6544 

6545masked = masked_singleton = MaskedConstant() 

6546masked_array = MaskedArray 

6547 

6548 

6549def array(data, dtype=None, copy=False, order=None, 

6550 mask=nomask, fill_value=None, keep_mask=True, 

6551 hard_mask=False, shrink=True, subok=True, ndmin=0): 

6552 """ 

6553 Shortcut to MaskedArray. 

6554 

6555 The options are in a different order for convenience and backwards 

6556 compatibility. 

6557 

6558 """ 

6559 return MaskedArray(data, mask=mask, dtype=dtype, copy=copy, 

6560 subok=subok, keep_mask=keep_mask, 

6561 hard_mask=hard_mask, fill_value=fill_value, 

6562 ndmin=ndmin, shrink=shrink, order=order) 

6563array.__doc__ = masked_array.__doc__ 

6564 

6565 

6566def is_masked(x): 

6567 """ 

6568 Determine whether input has masked values. 

6569 

6570 Accepts any object as input, but always returns False unless the 

6571 input is a MaskedArray containing masked values. 

6572 

6573 Parameters 

6574 ---------- 

6575 x : array_like 

6576 Array to check for masked values. 

6577 

6578 Returns 

6579 ------- 

6580 result : bool 

6581 True if `x` is a MaskedArray with masked values, False otherwise. 

6582 

6583 Examples 

6584 -------- 

6585 >>> import numpy.ma as ma 

6586 >>> x = ma.masked_equal([0, 1, 0, 2, 3], 0) 

6587 >>> x 

6588 masked_array(data=[--, 1, --, 2, 3], 

6589 mask=[ True, False, True, False, False], 

6590 fill_value=0) 

6591 >>> ma.is_masked(x) 

6592 True 

6593 >>> x = ma.masked_equal([0, 1, 0, 2, 3], 42) 

6594 >>> x 

6595 masked_array(data=[0, 1, 0, 2, 3], 

6596 mask=False, 

6597 fill_value=42) 

6598 >>> ma.is_masked(x) 

6599 False 

6600 

6601 Always returns False if `x` isn't a MaskedArray. 

6602 

6603 >>> x = [False, True, False] 

6604 >>> ma.is_masked(x) 

6605 False 

6606 >>> x = 'a string' 

6607 >>> ma.is_masked(x) 

6608 False 

6609 

6610 """ 

6611 m = getmask(x) 

6612 if m is nomask: 

6613 return False 

6614 elif m.any(): 

6615 return True 

6616 return False 

6617 

6618 

6619############################################################################## 

6620# Extrema functions # 

6621############################################################################## 

6622 

6623 

6624class _extrema_operation(_MaskedUFunc): 

6625 """ 

6626 Generic class for maximum/minimum functions. 

6627 

6628 .. note:: 

6629 This is the base class for `_maximum_operation` and 

6630 `_minimum_operation`. 

6631 

6632 """ 

6633 def __init__(self, ufunc, compare, fill_value): 

6634 super(_extrema_operation, self).__init__(ufunc) 

6635 self.compare = compare 

6636 self.fill_value_func = fill_value 

6637 

6638 def __call__(self, a, b=None): 

6639 "Executes the call behavior." 

6640 if b is None: 

6641 # 2016-04-13, 1.13.0 

6642 warnings.warn( 

6643 f"Single-argument form of np.ma.{self.__name__} is deprecated. Use " 

6644 f"np.ma.{self.__name__}.reduce instead.", 

6645 DeprecationWarning, stacklevel=2) 

6646 return self.reduce(a) 

6647 return where(self.compare(a, b), a, b) 

6648 

6649 def reduce(self, target, axis=np._NoValue): 

6650 "Reduce target along the given axis." 

6651 target = narray(target, copy=False, subok=True) 

6652 m = getmask(target) 

6653 

6654 if axis is np._NoValue and target.ndim > 1: 

6655 # 2017-05-06, Numpy 1.13.0: warn on axis default 

6656 warnings.warn( 

6657 f"In the future the default for ma.{self.__name__}.reduce will be axis=0, " 

6658 f"not the current None, to match np.{self.__name__}.reduce. " 

6659 "Explicitly pass 0 or None to silence this warning.", 

6660 MaskedArrayFutureWarning, stacklevel=2) 

6661 axis = None 

6662 

6663 if axis is not np._NoValue: 

6664 kwargs = dict(axis=axis) 

6665 else: 

6666 kwargs = dict() 

6667 

6668 if m is nomask: 

6669 t = self.f.reduce(target, **kwargs) 

6670 else: 

6671 target = target.filled( 

6672 self.fill_value_func(target)).view(type(target)) 

6673 t = self.f.reduce(target, **kwargs) 

6674 m = umath.logical_and.reduce(m, **kwargs) 

6675 if hasattr(t, '_mask'): 

6676 t._mask = m 

6677 elif m: 

6678 t = masked 

6679 return t 

6680 

6681 def outer(self, a, b): 

6682 "Return the function applied to the outer product of a and b." 

6683 ma = getmask(a) 

6684 mb = getmask(b) 

6685 if ma is nomask and mb is nomask: 

6686 m = nomask 

6687 else: 

6688 ma = getmaskarray(a) 

6689 mb = getmaskarray(b) 

6690 m = logical_or.outer(ma, mb) 

6691 result = self.f.outer(filled(a), filled(b)) 

6692 if not isinstance(result, MaskedArray): 

6693 result = result.view(MaskedArray) 

6694 result._mask = m 

6695 return result 

6696 

6697def min(obj, axis=None, out=None, fill_value=None, keepdims=np._NoValue): 

6698 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

6699 

6700 try: 

6701 return obj.min(axis=axis, fill_value=fill_value, out=out, **kwargs) 

6702 except (AttributeError, TypeError): 

6703 # If obj doesn't have a min method, or if the method doesn't accept a 

6704 # fill_value argument 

6705 return asanyarray(obj).min(axis=axis, fill_value=fill_value, 

6706 out=out, **kwargs) 

6707min.__doc__ = MaskedArray.min.__doc__ 

6708 

6709def max(obj, axis=None, out=None, fill_value=None, keepdims=np._NoValue): 

6710 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

6711 

6712 try: 

6713 return obj.max(axis=axis, fill_value=fill_value, out=out, **kwargs) 

6714 except (AttributeError, TypeError): 

6715 # If obj doesn't have a max method, or if the method doesn't accept a 

6716 # fill_value argument 

6717 return asanyarray(obj).max(axis=axis, fill_value=fill_value, 

6718 out=out, **kwargs) 

6719max.__doc__ = MaskedArray.max.__doc__ 

6720 

6721 

6722def ptp(obj, axis=None, out=None, fill_value=None, keepdims=np._NoValue): 

6723 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

6724 try: 

6725 return obj.ptp(axis, out=out, fill_value=fill_value, **kwargs) 

6726 except (AttributeError, TypeError): 

6727 # If obj doesn't have a ptp method or if the method doesn't accept 

6728 # a fill_value argument 

6729 return asanyarray(obj).ptp(axis=axis, fill_value=fill_value, 

6730 out=out, **kwargs) 

6731ptp.__doc__ = MaskedArray.ptp.__doc__ 

6732 

6733 

6734############################################################################## 

6735# Definition of functions from the corresponding methods # 

6736############################################################################## 

6737 

6738 

6739class _frommethod: 

6740 """ 

6741 Define functions from existing MaskedArray methods. 

6742 

6743 Parameters 

6744 ---------- 

6745 methodname : str 

6746 Name of the method to transform. 

6747 

6748 """ 

6749 

6750 def __init__(self, methodname, reversed=False): 

6751 self.__name__ = methodname 

6752 self.__doc__ = self.getdoc() 

6753 self.reversed = reversed 

6754 

6755 def getdoc(self): 

6756 "Return the doc of the function (from the doc of the method)." 

6757 meth = getattr(MaskedArray, self.__name__, None) or\ 

6758 getattr(np, self.__name__, None) 

6759 signature = self.__name__ + get_object_signature(meth) 

6760 if meth is not None: 

6761 doc = """ %s\n%s""" % ( 

6762 signature, getattr(meth, '__doc__', None)) 

6763 return doc 

6764 

6765 def __call__(self, a, *args, **params): 

6766 if self.reversed: 

6767 args = list(args) 

6768 a, args[0] = args[0], a 

6769 

6770 marr = asanyarray(a) 

6771 method_name = self.__name__ 

6772 method = getattr(type(marr), method_name, None) 

6773 if method is None: 

6774 # use the corresponding np function 

6775 method = getattr(np, method_name) 

6776 

6777 return method(marr, *args, **params) 

6778 

6779 

6780all = _frommethod('all') 

6781anomalies = anom = _frommethod('anom') 

6782any = _frommethod('any') 

6783compress = _frommethod('compress', reversed=True) 

6784cumprod = _frommethod('cumprod') 

6785cumsum = _frommethod('cumsum') 

6786copy = _frommethod('copy') 

6787diagonal = _frommethod('diagonal') 

6788harden_mask = _frommethod('harden_mask') 

6789ids = _frommethod('ids') 

6790maximum = _extrema_operation(umath.maximum, greater, maximum_fill_value) 

6791mean = _frommethod('mean') 

6792minimum = _extrema_operation(umath.minimum, less, minimum_fill_value) 

6793nonzero = _frommethod('nonzero') 

6794prod = _frommethod('prod') 

6795product = _frommethod('prod') 

6796ravel = _frommethod('ravel') 

6797repeat = _frommethod('repeat') 

6798shrink_mask = _frommethod('shrink_mask') 

6799soften_mask = _frommethod('soften_mask') 

6800std = _frommethod('std') 

6801sum = _frommethod('sum') 

6802swapaxes = _frommethod('swapaxes') 

6803#take = _frommethod('take') 

6804trace = _frommethod('trace') 

6805var = _frommethod('var') 

6806 

6807count = _frommethod('count') 

6808 

6809def take(a, indices, axis=None, out=None, mode='raise'): 

6810 """ 

6811 """ 

6812 a = masked_array(a) 

6813 return a.take(indices, axis=axis, out=out, mode=mode) 

6814 

6815 

6816def power(a, b, third=None): 

6817 """ 

6818 Returns element-wise base array raised to power from second array. 

6819 

6820 This is the masked array version of `numpy.power`. For details see 

6821 `numpy.power`. 

6822 

6823 See Also 

6824 -------- 

6825 numpy.power 

6826 

6827 Notes 

6828 ----- 

6829 The *out* argument to `numpy.power` is not supported, `third` has to be 

6830 None. 

6831 

6832 """ 

6833 if third is not None: 

6834 raise MaskError("3-argument power not supported.") 

6835 # Get the masks 

6836 ma = getmask(a) 

6837 mb = getmask(b) 

6838 m = mask_or(ma, mb) 

6839 # Get the rawdata 

6840 fa = getdata(a) 

6841 fb = getdata(b) 

6842 # Get the type of the result (so that we preserve subclasses) 

6843 if isinstance(a, MaskedArray): 

6844 basetype = type(a) 

6845 else: 

6846 basetype = MaskedArray 

6847 # Get the result and view it as a (subclass of) MaskedArray 

6848 with np.errstate(divide='ignore', invalid='ignore'): 

6849 result = np.where(m, fa, umath.power(fa, fb)).view(basetype) 

6850 result._update_from(a) 

6851 # Find where we're in trouble w/ NaNs and Infs 

6852 invalid = np.logical_not(np.isfinite(result.view(ndarray))) 

6853 # Add the initial mask 

6854 if m is not nomask: 

6855 if not result.ndim: 

6856 return masked 

6857 result._mask = np.logical_or(m, invalid) 

6858 # Fix the invalid parts 

6859 if invalid.any(): 

6860 if not result.ndim: 

6861 return masked 

6862 elif result._mask is nomask: 

6863 result._mask = invalid 

6864 result._data[invalid] = result.fill_value 

6865 return result 

6866 

6867argmin = _frommethod('argmin') 

6868argmax = _frommethod('argmax') 

6869 

6870def argsort(a, axis=np._NoValue, kind=None, order=None, endwith=True, fill_value=None): 

6871 "Function version of the eponymous method." 

6872 a = np.asanyarray(a) 

6873 

6874 # 2017-04-11, Numpy 1.13.0, gh-8701: warn on axis default 

6875 if axis is np._NoValue: 

6876 axis = _deprecate_argsort_axis(a) 

6877 

6878 if isinstance(a, MaskedArray): 

6879 return a.argsort(axis=axis, kind=kind, order=order, 

6880 endwith=endwith, fill_value=fill_value) 

6881 else: 

6882 return a.argsort(axis=axis, kind=kind, order=order) 

6883argsort.__doc__ = MaskedArray.argsort.__doc__ 

6884 

6885def sort(a, axis=-1, kind=None, order=None, endwith=True, fill_value=None): 

6886 """ 

6887 Return a sorted copy of the masked array. 

6888 

6889 Equivalent to creating a copy of the array 

6890 and applying the MaskedArray ``sort()`` method. 

6891 

6892 Refer to ``MaskedArray.sort`` for the full documentation 

6893 

6894 See Also 

6895 -------- 

6896 MaskedArray.sort : equivalent method 

6897 """ 

6898 a = np.array(a, copy=True, subok=True) 

6899 if axis is None: 

6900 a = a.flatten() 

6901 axis = 0 

6902 

6903 if isinstance(a, MaskedArray): 

6904 a.sort(axis=axis, kind=kind, order=order, 

6905 endwith=endwith, fill_value=fill_value) 

6906 else: 

6907 a.sort(axis=axis, kind=kind, order=order) 

6908 return a 

6909 

6910 

6911def compressed(x): 

6912 """ 

6913 Return all the non-masked data as a 1-D array. 

6914 

6915 This function is equivalent to calling the "compressed" method of a 

6916 `MaskedArray`, see `MaskedArray.compressed` for details. 

6917 

6918 See Also 

6919 -------- 

6920 MaskedArray.compressed 

6921 Equivalent method. 

6922 

6923 """ 

6924 return asanyarray(x).compressed() 

6925 

6926 

6927def concatenate(arrays, axis=0): 

6928 """ 

6929 Concatenate a sequence of arrays along the given axis. 

6930 

6931 Parameters 

6932 ---------- 

6933 arrays : sequence of array_like 

6934 The arrays must have the same shape, except in the dimension 

6935 corresponding to `axis` (the first, by default). 

6936 axis : int, optional 

6937 The axis along which the arrays will be joined. Default is 0. 

6938 

6939 Returns 

6940 ------- 

6941 result : MaskedArray 

6942 The concatenated array with any masked entries preserved. 

6943 

6944 See Also 

6945 -------- 

6946 numpy.concatenate : Equivalent function in the top-level NumPy module. 

6947 

6948 Examples 

6949 -------- 

6950 >>> import numpy.ma as ma 

6951 >>> a = ma.arange(3) 

6952 >>> a[1] = ma.masked 

6953 >>> b = ma.arange(2, 5) 

6954 >>> a 

6955 masked_array(data=[0, --, 2], 

6956 mask=[False, True, False], 

6957 fill_value=999999) 

6958 >>> b 

6959 masked_array(data=[2, 3, 4], 

6960 mask=False, 

6961 fill_value=999999) 

6962 >>> ma.concatenate([a, b]) 

6963 masked_array(data=[0, --, 2, 2, 3, 4], 

6964 mask=[False, True, False, False, False, False], 

6965 fill_value=999999) 

6966 

6967 """ 

6968 d = np.concatenate([getdata(a) for a in arrays], axis) 

6969 rcls = get_masked_subclass(*arrays) 

6970 data = d.view(rcls) 

6971 # Check whether one of the arrays has a non-empty mask. 

6972 for x in arrays: 

6973 if getmask(x) is not nomask: 

6974 break 

6975 else: 

6976 return data 

6977 # OK, so we have to concatenate the masks 

6978 dm = np.concatenate([getmaskarray(a) for a in arrays], axis) 

6979 dm = dm.reshape(d.shape) 

6980 

6981 # If we decide to keep a '_shrinkmask' option, we want to check that 

6982 # all of them are True, and then check for dm.any() 

6983 data._mask = _shrink_mask(dm) 

6984 return data 

6985 

6986 

6987def diag(v, k=0): 

6988 """ 

6989 Extract a diagonal or construct a diagonal array. 

6990 

6991 This function is the equivalent of `numpy.diag` that takes masked 

6992 values into account, see `numpy.diag` for details. 

6993 

6994 See Also 

6995 -------- 

6996 numpy.diag : Equivalent function for ndarrays. 

6997 

6998 """ 

6999 output = np.diag(v, k).view(MaskedArray) 

7000 if getmask(v) is not nomask: 

7001 output._mask = np.diag(v._mask, k) 

7002 return output 

7003 

7004 

7005def left_shift(a, n): 

7006 """ 

7007 Shift the bits of an integer to the left. 

7008 

7009 This is the masked array version of `numpy.left_shift`, for details 

7010 see that function. 

7011 

7012 See Also 

7013 -------- 

7014 numpy.left_shift 

7015 

7016 """ 

7017 m = getmask(a) 

7018 if m is nomask: 

7019 d = umath.left_shift(filled(a), n) 

7020 return masked_array(d) 

7021 else: 

7022 d = umath.left_shift(filled(a, 0), n) 

7023 return masked_array(d, mask=m) 

7024 

7025 

7026def right_shift(a, n): 

7027 """ 

7028 Shift the bits of an integer to the right. 

7029 

7030 This is the masked array version of `numpy.right_shift`, for details 

7031 see that function. 

7032 

7033 See Also 

7034 -------- 

7035 numpy.right_shift 

7036 

7037 """ 

7038 m = getmask(a) 

7039 if m is nomask: 

7040 d = umath.right_shift(filled(a), n) 

7041 return masked_array(d) 

7042 else: 

7043 d = umath.right_shift(filled(a, 0), n) 

7044 return masked_array(d, mask=m) 

7045 

7046 

7047def put(a, indices, values, mode='raise'): 

7048 """ 

7049 Set storage-indexed locations to corresponding values. 

7050 

7051 This function is equivalent to `MaskedArray.put`, see that method 

7052 for details. 

7053 

7054 See Also 

7055 -------- 

7056 MaskedArray.put 

7057 

7058 """ 

7059 # We can't use 'frommethod', the order of arguments is different 

7060 try: 

7061 return a.put(indices, values, mode=mode) 

7062 except AttributeError: 

7063 return narray(a, copy=False).put(indices, values, mode=mode) 

7064 

7065 

7066def putmask(a, mask, values): # , mode='raise'): 

7067 """ 

7068 Changes elements of an array based on conditional and input values. 

7069 

7070 This is the masked array version of `numpy.putmask`, for details see 

7071 `numpy.putmask`. 

7072 

7073 See Also 

7074 -------- 

7075 numpy.putmask 

7076 

7077 Notes 

7078 ----- 

7079 Using a masked array as `values` will **not** transform a `ndarray` into 

7080 a `MaskedArray`. 

7081 

7082 """ 

7083 # We can't use 'frommethod', the order of arguments is different 

7084 if not isinstance(a, MaskedArray): 

7085 a = a.view(MaskedArray) 

7086 (valdata, valmask) = (getdata(values), getmask(values)) 

7087 if getmask(a) is nomask: 

7088 if valmask is not nomask: 

7089 a._sharedmask = True 

7090 a._mask = make_mask_none(a.shape, a.dtype) 

7091 np.copyto(a._mask, valmask, where=mask) 

7092 elif a._hardmask: 

7093 if valmask is not nomask: 

7094 m = a._mask.copy() 

7095 np.copyto(m, valmask, where=mask) 

7096 a.mask |= m 

7097 else: 

7098 if valmask is nomask: 

7099 valmask = getmaskarray(values) 

7100 np.copyto(a._mask, valmask, where=mask) 

7101 np.copyto(a._data, valdata, where=mask) 

7102 return 

7103 

7104 

7105def transpose(a, axes=None): 

7106 """ 

7107 Permute the dimensions of an array. 

7108 

7109 This function is exactly equivalent to `numpy.transpose`. 

7110 

7111 See Also 

7112 -------- 

7113 numpy.transpose : Equivalent function in top-level NumPy module. 

7114 

7115 Examples 

7116 -------- 

7117 >>> import numpy.ma as ma 

7118 >>> x = ma.arange(4).reshape((2,2)) 

7119 >>> x[1, 1] = ma.masked 

7120 >>> x 

7121 masked_array( 

7122 data=[[0, 1], 

7123 [2, --]], 

7124 mask=[[False, False], 

7125 [False, True]], 

7126 fill_value=999999) 

7127 

7128 >>> ma.transpose(x) 

7129 masked_array( 

7130 data=[[0, 2], 

7131 [1, --]], 

7132 mask=[[False, False], 

7133 [False, True]], 

7134 fill_value=999999) 

7135 """ 

7136 # We can't use 'frommethod', as 'transpose' doesn't take keywords 

7137 try: 

7138 return a.transpose(axes) 

7139 except AttributeError: 

7140 return narray(a, copy=False).transpose(axes).view(MaskedArray) 

7141 

7142 

7143def reshape(a, new_shape, order='C'): 

7144 """ 

7145 Returns an array containing the same data with a new shape. 

7146 

7147 Refer to `MaskedArray.reshape` for full documentation. 

7148 

7149 See Also 

7150 -------- 

7151 MaskedArray.reshape : equivalent function 

7152 

7153 """ 

7154 # We can't use 'frommethod', it whine about some parameters. Dmmit. 

7155 try: 

7156 return a.reshape(new_shape, order=order) 

7157 except AttributeError: 

7158 _tmp = narray(a, copy=False).reshape(new_shape, order=order) 

7159 return _tmp.view(MaskedArray) 

7160 

7161 

7162def resize(x, new_shape): 

7163 """ 

7164 Return a new masked array with the specified size and shape. 

7165 

7166 This is the masked equivalent of the `numpy.resize` function. The new 

7167 array is filled with repeated copies of `x` (in the order that the 

7168 data are stored in memory). If `x` is masked, the new array will be 

7169 masked, and the new mask will be a repetition of the old one. 

7170 

7171 See Also 

7172 -------- 

7173 numpy.resize : Equivalent function in the top level NumPy module. 

7174 

7175 Examples 

7176 -------- 

7177 >>> import numpy.ma as ma 

7178 >>> a = ma.array([[1, 2] ,[3, 4]]) 

7179 >>> a[0, 1] = ma.masked 

7180 >>> a 

7181 masked_array( 

7182 data=[[1, --], 

7183 [3, 4]], 

7184 mask=[[False, True], 

7185 [False, False]], 

7186 fill_value=999999) 

7187 >>> np.resize(a, (3, 3)) 

7188 masked_array( 

7189 data=[[1, 2, 3], 

7190 [4, 1, 2], 

7191 [3, 4, 1]], 

7192 mask=False, 

7193 fill_value=999999) 

7194 >>> ma.resize(a, (3, 3)) 

7195 masked_array( 

7196 data=[[1, --, 3], 

7197 [4, 1, --], 

7198 [3, 4, 1]], 

7199 mask=[[False, True, False], 

7200 [False, False, True], 

7201 [False, False, False]], 

7202 fill_value=999999) 

7203 

7204 A MaskedArray is always returned, regardless of the input type. 

7205 

7206 >>> a = np.array([[1, 2] ,[3, 4]]) 

7207 >>> ma.resize(a, (3, 3)) 

7208 masked_array( 

7209 data=[[1, 2, 3], 

7210 [4, 1, 2], 

7211 [3, 4, 1]], 

7212 mask=False, 

7213 fill_value=999999) 

7214 

7215 """ 

7216 # We can't use _frommethods here, as N.resize is notoriously whiny. 

7217 m = getmask(x) 

7218 if m is not nomask: 

7219 m = np.resize(m, new_shape) 

7220 result = np.resize(x, new_shape).view(get_masked_subclass(x)) 

7221 if result.ndim: 

7222 result._mask = m 

7223 return result 

7224 

7225 

7226def ndim(obj): 

7227 """ 

7228 maskedarray version of the numpy function. 

7229 

7230 """ 

7231 return np.ndim(getdata(obj)) 

7232 

7233ndim.__doc__ = np.ndim.__doc__ 

7234 

7235 

7236def shape(obj): 

7237 "maskedarray version of the numpy function." 

7238 return np.shape(getdata(obj)) 

7239shape.__doc__ = np.shape.__doc__ 

7240 

7241 

7242def size(obj, axis=None): 

7243 "maskedarray version of the numpy function." 

7244 return np.size(getdata(obj), axis) 

7245size.__doc__ = np.size.__doc__ 

7246 

7247 

7248############################################################################## 

7249# Extra functions # 

7250############################################################################## 

7251 

7252 

7253def where(condition, x=_NoValue, y=_NoValue): 

7254 """ 

7255 Return a masked array with elements from `x` or `y`, depending on condition. 

7256 

7257 .. note:: 

7258 When only `condition` is provided, this function is identical to 

7259 `nonzero`. The rest of this documentation covers only the case where 

7260 all three arguments are provided. 

7261 

7262 Parameters 

7263 ---------- 

7264 condition : array_like, bool 

7265 Where True, yield `x`, otherwise yield `y`. 

7266 x, y : array_like, optional 

7267 Values from which to choose. `x`, `y` and `condition` need to be 

7268 broadcastable to some shape. 

7269 

7270 Returns 

7271 ------- 

7272 out : MaskedArray 

7273 An masked array with `masked` elements where the condition is masked, 

7274 elements from `x` where `condition` is True, and elements from `y` 

7275 elsewhere. 

7276 

7277 See Also 

7278 -------- 

7279 numpy.where : Equivalent function in the top-level NumPy module. 

7280 nonzero : The function that is called when x and y are omitted 

7281 

7282 Examples 

7283 -------- 

7284 >>> x = np.ma.array(np.arange(9.).reshape(3, 3), mask=[[0, 1, 0], 

7285 ... [1, 0, 1], 

7286 ... [0, 1, 0]]) 

7287 >>> x 

7288 masked_array( 

7289 data=[[0.0, --, 2.0], 

7290 [--, 4.0, --], 

7291 [6.0, --, 8.0]], 

7292 mask=[[False, True, False], 

7293 [ True, False, True], 

7294 [False, True, False]], 

7295 fill_value=1e+20) 

7296 >>> np.ma.where(x > 5, x, -3.1416) 

7297 masked_array( 

7298 data=[[-3.1416, --, -3.1416], 

7299 [--, -3.1416, --], 

7300 [6.0, --, 8.0]], 

7301 mask=[[False, True, False], 

7302 [ True, False, True], 

7303 [False, True, False]], 

7304 fill_value=1e+20) 

7305 

7306 """ 

7307 

7308 # handle the single-argument case 

7309 missing = (x is _NoValue, y is _NoValue).count(True) 

7310 if missing == 1: 

7311 raise ValueError("Must provide both 'x' and 'y' or neither.") 

7312 if missing == 2: 

7313 return nonzero(condition) 

7314 

7315 # we only care if the condition is true - false or masked pick y 

7316 cf = filled(condition, False) 

7317 xd = getdata(x) 

7318 yd = getdata(y) 

7319 

7320 # we need the full arrays here for correct final dimensions 

7321 cm = getmaskarray(condition) 

7322 xm = getmaskarray(x) 

7323 ym = getmaskarray(y) 

7324 

7325 # deal with the fact that masked.dtype == float64, but we don't actually 

7326 # want to treat it as that. 

7327 if x is masked and y is not masked: 

7328 xd = np.zeros((), dtype=yd.dtype) 

7329 xm = np.ones((), dtype=ym.dtype) 

7330 elif y is masked and x is not masked: 

7331 yd = np.zeros((), dtype=xd.dtype) 

7332 ym = np.ones((), dtype=xm.dtype) 

7333 

7334 data = np.where(cf, xd, yd) 

7335 mask = np.where(cf, xm, ym) 

7336 mask = np.where(cm, np.ones((), dtype=mask.dtype), mask) 

7337 

7338 # collapse the mask, for backwards compatibility 

7339 mask = _shrink_mask(mask) 

7340 

7341 return masked_array(data, mask=mask) 

7342 

7343 

7344def choose(indices, choices, out=None, mode='raise'): 

7345 """ 

7346 Use an index array to construct a new array from a set of choices. 

7347 

7348 Given an array of integers and a set of n choice arrays, this method 

7349 will create a new array that merges each of the choice arrays. Where a 

7350 value in `a` is i, the new array will have the value that choices[i] 

7351 contains in the same place. 

7352 

7353 Parameters 

7354 ---------- 

7355 a : ndarray of ints 

7356 This array must contain integers in ``[0, n-1]``, where n is the 

7357 number of choices. 

7358 choices : sequence of arrays 

7359 Choice arrays. The index array and all of the choices should be 

7360 broadcastable to the same shape. 

7361 out : array, optional 

7362 If provided, the result will be inserted into this array. It should 

7363 be of the appropriate shape and `dtype`. 

7364 mode : {'raise', 'wrap', 'clip'}, optional 

7365 Specifies how out-of-bounds indices will behave. 

7366 

7367 * 'raise' : raise an error 

7368 * 'wrap' : wrap around 

7369 * 'clip' : clip to the range 

7370 

7371 Returns 

7372 ------- 

7373 merged_array : array 

7374 

7375 See Also 

7376 -------- 

7377 choose : equivalent function 

7378 

7379 Examples 

7380 -------- 

7381 >>> choice = np.array([[1,1,1], [2,2,2], [3,3,3]]) 

7382 >>> a = np.array([2, 1, 0]) 

7383 >>> np.ma.choose(a, choice) 

7384 masked_array(data=[3, 2, 1], 

7385 mask=False, 

7386 fill_value=999999) 

7387 

7388 """ 

7389 def fmask(x): 

7390 "Returns the filled array, or True if masked." 

7391 if x is masked: 

7392 return True 

7393 return filled(x) 

7394 

7395 def nmask(x): 

7396 "Returns the mask, True if ``masked``, False if ``nomask``." 

7397 if x is masked: 

7398 return True 

7399 return getmask(x) 

7400 # Get the indices. 

7401 c = filled(indices, 0) 

7402 # Get the masks. 

7403 masks = [nmask(x) for x in choices] 

7404 data = [fmask(x) for x in choices] 

7405 # Construct the mask 

7406 outputmask = np.choose(c, masks, mode=mode) 

7407 outputmask = make_mask(mask_or(outputmask, getmask(indices)), 

7408 copy=False, shrink=True) 

7409 # Get the choices. 

7410 d = np.choose(c, data, mode=mode, out=out).view(MaskedArray) 

7411 if out is not None: 

7412 if isinstance(out, MaskedArray): 

7413 out.__setmask__(outputmask) 

7414 return out 

7415 d.__setmask__(outputmask) 

7416 return d 

7417 

7418 

7419def round_(a, decimals=0, out=None): 

7420 """ 

7421 Return a copy of a, rounded to 'decimals' places. 

7422 

7423 When 'decimals' is negative, it specifies the number of positions 

7424 to the left of the decimal point. The real and imaginary parts of 

7425 complex numbers are rounded separately. Nothing is done if the 

7426 array is not of float type and 'decimals' is greater than or equal 

7427 to 0. 

7428 

7429 Parameters 

7430 ---------- 

7431 decimals : int 

7432 Number of decimals to round to. May be negative. 

7433 out : array_like 

7434 Existing array to use for output. 

7435 If not given, returns a default copy of a. 

7436 

7437 Notes 

7438 ----- 

7439 If out is given and does not have a mask attribute, the mask of a 

7440 is lost! 

7441 

7442 """ 

7443 if out is None: 

7444 return np.round_(a, decimals, out) 

7445 else: 

7446 np.round_(getdata(a), decimals, out) 

7447 if hasattr(out, '_mask'): 

7448 out._mask = getmask(a) 

7449 return out 

7450round = round_ 

7451 

7452 

7453# Needed by dot, so move here from extras.py. It will still be exported 

7454# from extras.py for compatibility. 

7455def mask_rowcols(a, axis=None): 

7456 """ 

7457 Mask rows and/or columns of a 2D array that contain masked values. 

7458 

7459 Mask whole rows and/or columns of a 2D array that contain 

7460 masked values. The masking behavior is selected using the 

7461 `axis` parameter. 

7462 

7463 - If `axis` is None, rows *and* columns are masked. 

7464 - If `axis` is 0, only rows are masked. 

7465 - If `axis` is 1 or -1, only columns are masked. 

7466 

7467 Parameters 

7468 ---------- 

7469 a : array_like, MaskedArray 

7470 The array to mask. If not a MaskedArray instance (or if no array 

7471 elements are masked). The result is a MaskedArray with `mask` set 

7472 to `nomask` (False). Must be a 2D array. 

7473 axis : int, optional 

7474 Axis along which to perform the operation. If None, applies to a 

7475 flattened version of the array. 

7476 

7477 Returns 

7478 ------- 

7479 a : MaskedArray 

7480 A modified version of the input array, masked depending on the value 

7481 of the `axis` parameter. 

7482 

7483 Raises 

7484 ------ 

7485 NotImplementedError 

7486 If input array `a` is not 2D. 

7487 

7488 See Also 

7489 -------- 

7490 mask_rows : Mask rows of a 2D array that contain masked values. 

7491 mask_cols : Mask cols of a 2D array that contain masked values. 

7492 masked_where : Mask where a condition is met. 

7493 

7494 Notes 

7495 ----- 

7496 The input array's mask is modified by this function. 

7497 

7498 Examples 

7499 -------- 

7500 >>> import numpy.ma as ma 

7501 >>> a = np.zeros((3, 3), dtype=int) 

7502 >>> a[1, 1] = 1 

7503 >>> a 

7504 array([[0, 0, 0], 

7505 [0, 1, 0], 

7506 [0, 0, 0]]) 

7507 >>> a = ma.masked_equal(a, 1) 

7508 >>> a 

7509 masked_array( 

7510 data=[[0, 0, 0], 

7511 [0, --, 0], 

7512 [0, 0, 0]], 

7513 mask=[[False, False, False], 

7514 [False, True, False], 

7515 [False, False, False]], 

7516 fill_value=1) 

7517 >>> ma.mask_rowcols(a) 

7518 masked_array( 

7519 data=[[0, --, 0], 

7520 [--, --, --], 

7521 [0, --, 0]], 

7522 mask=[[False, True, False], 

7523 [ True, True, True], 

7524 [False, True, False]], 

7525 fill_value=1) 

7526 

7527 """ 

7528 a = array(a, subok=False) 

7529 if a.ndim != 2: 

7530 raise NotImplementedError("mask_rowcols works for 2D arrays only.") 

7531 m = getmask(a) 

7532 # Nothing is masked: return a 

7533 if m is nomask or not m.any(): 

7534 return a 

7535 maskedval = m.nonzero() 

7536 a._mask = a._mask.copy() 

7537 if not axis: 

7538 a[np.unique(maskedval[0])] = masked 

7539 if axis in [None, 1, -1]: 

7540 a[:, np.unique(maskedval[1])] = masked 

7541 return a 

7542 

7543 

7544# Include masked dot here to avoid import problems in getting it from 

7545# extras.py. Note that it is not included in __all__, but rather exported 

7546# from extras in order to avoid backward compatibility problems. 

7547def dot(a, b, strict=False, out=None): 

7548 """ 

7549 Return the dot product of two arrays. 

7550 

7551 This function is the equivalent of `numpy.dot` that takes masked values 

7552 into account. Note that `strict` and `out` are in different position 

7553 than in the method version. In order to maintain compatibility with the 

7554 corresponding method, it is recommended that the optional arguments be 

7555 treated as keyword only. At some point that may be mandatory. 

7556 

7557 .. note:: 

7558 Works only with 2-D arrays at the moment. 

7559 

7560 

7561 Parameters 

7562 ---------- 

7563 a, b : masked_array_like 

7564 Inputs arrays. 

7565 strict : bool, optional 

7566 Whether masked data are propagated (True) or set to 0 (False) for 

7567 the computation. Default is False. Propagating the mask means that 

7568 if a masked value appears in a row or column, the whole row or 

7569 column is considered masked. 

7570 out : masked_array, optional 

7571 Output argument. This must have the exact kind that would be returned 

7572 if it was not used. In particular, it must have the right type, must be 

7573 C-contiguous, and its dtype must be the dtype that would be returned 

7574 for `dot(a,b)`. This is a performance feature. Therefore, if these 

7575 conditions are not met, an exception is raised, instead of attempting 

7576 to be flexible. 

7577 

7578 .. versionadded:: 1.10.2 

7579 

7580 See Also 

7581 -------- 

7582 numpy.dot : Equivalent function for ndarrays. 

7583 

7584 Examples 

7585 -------- 

7586 >>> a = np.ma.array([[1, 2, 3], [4, 5, 6]], mask=[[1, 0, 0], [0, 0, 0]]) 

7587 >>> b = np.ma.array([[1, 2], [3, 4], [5, 6]], mask=[[1, 0], [0, 0], [0, 0]]) 

7588 >>> np.ma.dot(a, b) 

7589 masked_array( 

7590 data=[[21, 26], 

7591 [45, 64]], 

7592 mask=[[False, False], 

7593 [False, False]], 

7594 fill_value=999999) 

7595 >>> np.ma.dot(a, b, strict=True) 

7596 masked_array( 

7597 data=[[--, --], 

7598 [--, 64]], 

7599 mask=[[ True, True], 

7600 [ True, False]], 

7601 fill_value=999999) 

7602 

7603 """ 

7604 # !!!: Works only with 2D arrays. There should be a way to get it to run 

7605 # with higher dimension 

7606 if strict and (a.ndim == 2) and (b.ndim == 2): 

7607 a = mask_rowcols(a, 0) 

7608 b = mask_rowcols(b, 1) 

7609 am = ~getmaskarray(a) 

7610 bm = ~getmaskarray(b) 

7611 

7612 if out is None: 

7613 d = np.dot(filled(a, 0), filled(b, 0)) 

7614 m = ~np.dot(am, bm) 

7615 if d.ndim == 0: 

7616 d = np.asarray(d) 

7617 r = d.view(get_masked_subclass(a, b)) 

7618 r.__setmask__(m) 

7619 return r 

7620 else: 

7621 d = np.dot(filled(a, 0), filled(b, 0), out._data) 

7622 if out.mask.shape != d.shape: 

7623 out._mask = np.empty(d.shape, MaskType) 

7624 np.dot(am, bm, out._mask) 

7625 np.logical_not(out._mask, out._mask) 

7626 return out 

7627 

7628 

7629def inner(a, b): 

7630 """ 

7631 Returns the inner product of a and b for arrays of floating point types. 

7632 

7633 Like the generic NumPy equivalent the product sum is over the last dimension 

7634 of a and b. The first argument is not conjugated. 

7635 

7636 """ 

7637 fa = filled(a, 0) 

7638 fb = filled(b, 0) 

7639 if fa.ndim == 0: 

7640 fa.shape = (1,) 

7641 if fb.ndim == 0: 

7642 fb.shape = (1,) 

7643 return np.inner(fa, fb).view(MaskedArray) 

7644inner.__doc__ = doc_note(np.inner.__doc__, 

7645 "Masked values are replaced by 0.") 

7646innerproduct = inner 

7647 

7648 

7649def outer(a, b): 

7650 "maskedarray version of the numpy function." 

7651 fa = filled(a, 0).ravel() 

7652 fb = filled(b, 0).ravel() 

7653 d = np.outer(fa, fb) 

7654 ma = getmask(a) 

7655 mb = getmask(b) 

7656 if ma is nomask and mb is nomask: 

7657 return masked_array(d) 

7658 ma = getmaskarray(a) 

7659 mb = getmaskarray(b) 

7660 m = make_mask(1 - np.outer(1 - ma, 1 - mb), copy=False) 

7661 return masked_array(d, mask=m) 

7662outer.__doc__ = doc_note(np.outer.__doc__, 

7663 "Masked values are replaced by 0.") 

7664outerproduct = outer 

7665 

7666 

7667def _convolve_or_correlate(f, a, v, mode, propagate_mask): 

7668 """ 

7669 Helper function for ma.correlate and ma.convolve 

7670 """ 

7671 if propagate_mask: 

7672 # results which are contributed to by either item in any pair being invalid 

7673 mask = ( 

7674 f(getmaskarray(a), np.ones(np.shape(v), dtype=bool), mode=mode) 

7675 | f(np.ones(np.shape(a), dtype=bool), getmaskarray(v), mode=mode) 

7676 ) 

7677 data = f(getdata(a), getdata(v), mode=mode) 

7678 else: 

7679 # results which are not contributed to by any pair of valid elements 

7680 mask = ~f(~getmaskarray(a), ~getmaskarray(v)) 

7681 data = f(filled(a, 0), filled(v, 0), mode=mode) 

7682 

7683 return masked_array(data, mask=mask) 

7684 

7685 

7686def correlate(a, v, mode='valid', propagate_mask=True): 

7687 """ 

7688 Cross-correlation of two 1-dimensional sequences. 

7689 

7690 Parameters 

7691 ---------- 

7692 a, v : array_like 

7693 Input sequences. 

7694 mode : {'valid', 'same', 'full'}, optional 

7695 Refer to the `np.convolve` docstring. Note that the default 

7696 is 'valid', unlike `convolve`, which uses 'full'. 

7697 propagate_mask : bool 

7698 If True, then a result element is masked if any masked element contributes towards it. 

7699 If False, then a result element is only masked if no non-masked element 

7700 contribute towards it 

7701 

7702 Returns 

7703 ------- 

7704 out : MaskedArray 

7705 Discrete cross-correlation of `a` and `v`. 

7706 

7707 See Also 

7708 -------- 

7709 numpy.correlate : Equivalent function in the top-level NumPy module. 

7710 """ 

7711 return _convolve_or_correlate(np.correlate, a, v, mode, propagate_mask) 

7712 

7713 

7714def convolve(a, v, mode='full', propagate_mask=True): 

7715 """ 

7716 Returns the discrete, linear convolution of two one-dimensional sequences. 

7717 

7718 Parameters 

7719 ---------- 

7720 a, v : array_like 

7721 Input sequences. 

7722 mode : {'valid', 'same', 'full'}, optional 

7723 Refer to the `np.convolve` docstring. 

7724 propagate_mask : bool 

7725 If True, then if any masked element is included in the sum for a result 

7726 element, then the result is masked. 

7727 If False, then the result element is only masked if no non-masked cells 

7728 contribute towards it 

7729 

7730 Returns 

7731 ------- 

7732 out : MaskedArray 

7733 Discrete, linear convolution of `a` and `v`. 

7734 

7735 See Also 

7736 -------- 

7737 numpy.convolve : Equivalent function in the top-level NumPy module. 

7738 """ 

7739 return _convolve_or_correlate(np.convolve, a, v, mode, propagate_mask) 

7740 

7741 

7742def allequal(a, b, fill_value=True): 

7743 """ 

7744 Return True if all entries of a and b are equal, using 

7745 fill_value as a truth value where either or both are masked. 

7746 

7747 Parameters 

7748 ---------- 

7749 a, b : array_like 

7750 Input arrays to compare. 

7751 fill_value : bool, optional 

7752 Whether masked values in a or b are considered equal (True) or not 

7753 (False). 

7754 

7755 Returns 

7756 ------- 

7757 y : bool 

7758 Returns True if the two arrays are equal within the given 

7759 tolerance, False otherwise. If either array contains NaN, 

7760 then False is returned. 

7761 

7762 See Also 

7763 -------- 

7764 all, any 

7765 numpy.ma.allclose 

7766 

7767 Examples 

7768 -------- 

7769 >>> a = np.ma.array([1e10, 1e-7, 42.0], mask=[0, 0, 1]) 

7770 >>> a 

7771 masked_array(data=[10000000000.0, 1e-07, --], 

7772 mask=[False, False, True], 

7773 fill_value=1e+20) 

7774 

7775 >>> b = np.array([1e10, 1e-7, -42.0]) 

7776 >>> b 

7777 array([ 1.00000000e+10, 1.00000000e-07, -4.20000000e+01]) 

7778 >>> np.ma.allequal(a, b, fill_value=False) 

7779 False 

7780 >>> np.ma.allequal(a, b) 

7781 True 

7782 

7783 """ 

7784 m = mask_or(getmask(a), getmask(b)) 

7785 if m is nomask: 

7786 x = getdata(a) 

7787 y = getdata(b) 

7788 d = umath.equal(x, y) 

7789 return d.all() 

7790 elif fill_value: 

7791 x = getdata(a) 

7792 y = getdata(b) 

7793 d = umath.equal(x, y) 

7794 dm = array(d, mask=m, copy=False) 

7795 return dm.filled(True).all(None) 

7796 else: 

7797 return False 

7798 

7799 

7800def allclose(a, b, masked_equal=True, rtol=1e-5, atol=1e-8): 

7801 """ 

7802 Returns True if two arrays are element-wise equal within a tolerance. 

7803 

7804 This function is equivalent to `allclose` except that masked values 

7805 are treated as equal (default) or unequal, depending on the `masked_equal` 

7806 argument. 

7807 

7808 Parameters 

7809 ---------- 

7810 a, b : array_like 

7811 Input arrays to compare. 

7812 masked_equal : bool, optional 

7813 Whether masked values in `a` and `b` are considered equal (True) or not 

7814 (False). They are considered equal by default. 

7815 rtol : float, optional 

7816 Relative tolerance. The relative difference is equal to ``rtol * b``. 

7817 Default is 1e-5. 

7818 atol : float, optional 

7819 Absolute tolerance. The absolute difference is equal to `atol`. 

7820 Default is 1e-8. 

7821 

7822 Returns 

7823 ------- 

7824 y : bool 

7825 Returns True if the two arrays are equal within the given 

7826 tolerance, False otherwise. If either array contains NaN, then 

7827 False is returned. 

7828 

7829 See Also 

7830 -------- 

7831 all, any 

7832 numpy.allclose : the non-masked `allclose`. 

7833 

7834 Notes 

7835 ----- 

7836 If the following equation is element-wise True, then `allclose` returns 

7837 True:: 

7838 

7839 absolute(`a` - `b`) <= (`atol` + `rtol` * absolute(`b`)) 

7840 

7841 Return True if all elements of `a` and `b` are equal subject to 

7842 given tolerances. 

7843 

7844 Examples 

7845 -------- 

7846 >>> a = np.ma.array([1e10, 1e-7, 42.0], mask=[0, 0, 1]) 

7847 >>> a 

7848 masked_array(data=[10000000000.0, 1e-07, --], 

7849 mask=[False, False, True], 

7850 fill_value=1e+20) 

7851 >>> b = np.ma.array([1e10, 1e-8, -42.0], mask=[0, 0, 1]) 

7852 >>> np.ma.allclose(a, b) 

7853 False 

7854 

7855 >>> a = np.ma.array([1e10, 1e-8, 42.0], mask=[0, 0, 1]) 

7856 >>> b = np.ma.array([1.00001e10, 1e-9, -42.0], mask=[0, 0, 1]) 

7857 >>> np.ma.allclose(a, b) 

7858 True 

7859 >>> np.ma.allclose(a, b, masked_equal=False) 

7860 False 

7861 

7862 Masked values are not compared directly. 

7863 

7864 >>> a = np.ma.array([1e10, 1e-8, 42.0], mask=[0, 0, 1]) 

7865 >>> b = np.ma.array([1.00001e10, 1e-9, 42.0], mask=[0, 0, 1]) 

7866 >>> np.ma.allclose(a, b) 

7867 True 

7868 >>> np.ma.allclose(a, b, masked_equal=False) 

7869 False 

7870 

7871 """ 

7872 x = masked_array(a, copy=False) 

7873 y = masked_array(b, copy=False) 

7874 

7875 # make sure y is an inexact type to avoid abs(MIN_INT); will cause 

7876 # casting of x later. 

7877 dtype = np.result_type(y, 1.) 

7878 if y.dtype != dtype: 

7879 y = masked_array(y, dtype=dtype, copy=False) 

7880 

7881 m = mask_or(getmask(x), getmask(y)) 

7882 xinf = np.isinf(masked_array(x, copy=False, mask=m)).filled(False) 

7883 # If we have some infs, they should fall at the same place. 

7884 if not np.all(xinf == filled(np.isinf(y), False)): 

7885 return False 

7886 # No infs at all 

7887 if not np.any(xinf): 

7888 d = filled(less_equal(absolute(x - y), atol + rtol * absolute(y)), 

7889 masked_equal) 

7890 return np.all(d) 

7891 

7892 if not np.all(filled(x[xinf] == y[xinf], masked_equal)): 

7893 return False 

7894 x = x[~xinf] 

7895 y = y[~xinf] 

7896 

7897 d = filled(less_equal(absolute(x - y), atol + rtol * absolute(y)), 

7898 masked_equal) 

7899 

7900 return np.all(d) 

7901 

7902 

7903def asarray(a, dtype=None, order=None): 

7904 """ 

7905 Convert the input to a masked array of the given data-type. 

7906 

7907 No copy is performed if the input is already an `ndarray`. If `a` is 

7908 a subclass of `MaskedArray`, a base class `MaskedArray` is returned. 

7909 

7910 Parameters 

7911 ---------- 

7912 a : array_like 

7913 Input data, in any form that can be converted to a masked array. This 

7914 includes lists, lists of tuples, tuples, tuples of tuples, tuples 

7915 of lists, ndarrays and masked arrays. 

7916 dtype : dtype, optional 

7917 By default, the data-type is inferred from the input data. 

7918 order : {'C', 'F'}, optional 

7919 Whether to use row-major ('C') or column-major ('FORTRAN') memory 

7920 representation. Default is 'C'. 

7921 

7922 Returns 

7923 ------- 

7924 out : MaskedArray 

7925 Masked array interpretation of `a`. 

7926 

7927 See Also 

7928 -------- 

7929 asanyarray : Similar to `asarray`, but conserves subclasses. 

7930 

7931 Examples 

7932 -------- 

7933 >>> x = np.arange(10.).reshape(2, 5) 

7934 >>> x 

7935 array([[0., 1., 2., 3., 4.], 

7936 [5., 6., 7., 8., 9.]]) 

7937 >>> np.ma.asarray(x) 

7938 masked_array( 

7939 data=[[0., 1., 2., 3., 4.], 

7940 [5., 6., 7., 8., 9.]], 

7941 mask=False, 

7942 fill_value=1e+20) 

7943 >>> type(np.ma.asarray(x)) 

7944 <class 'numpy.ma.core.MaskedArray'> 

7945 

7946 """ 

7947 order = order or 'C' 

7948 return masked_array(a, dtype=dtype, copy=False, keep_mask=True, 

7949 subok=False, order=order) 

7950 

7951 

7952def asanyarray(a, dtype=None): 

7953 """ 

7954 Convert the input to a masked array, conserving subclasses. 

7955 

7956 If `a` is a subclass of `MaskedArray`, its class is conserved. 

7957 No copy is performed if the input is already an `ndarray`. 

7958 

7959 Parameters 

7960 ---------- 

7961 a : array_like 

7962 Input data, in any form that can be converted to an array. 

7963 dtype : dtype, optional 

7964 By default, the data-type is inferred from the input data. 

7965 order : {'C', 'F'}, optional 

7966 Whether to use row-major ('C') or column-major ('FORTRAN') memory 

7967 representation. Default is 'C'. 

7968 

7969 Returns 

7970 ------- 

7971 out : MaskedArray 

7972 MaskedArray interpretation of `a`. 

7973 

7974 See Also 

7975 -------- 

7976 asarray : Similar to `asanyarray`, but does not conserve subclass. 

7977 

7978 Examples 

7979 -------- 

7980 >>> x = np.arange(10.).reshape(2, 5) 

7981 >>> x 

7982 array([[0., 1., 2., 3., 4.], 

7983 [5., 6., 7., 8., 9.]]) 

7984 >>> np.ma.asanyarray(x) 

7985 masked_array( 

7986 data=[[0., 1., 2., 3., 4.], 

7987 [5., 6., 7., 8., 9.]], 

7988 mask=False, 

7989 fill_value=1e+20) 

7990 >>> type(np.ma.asanyarray(x)) 

7991 <class 'numpy.ma.core.MaskedArray'> 

7992 

7993 """ 

7994 # workaround for #8666, to preserve identity. Ideally the bottom line 

7995 # would handle this for us. 

7996 if isinstance(a, MaskedArray) and (dtype is None or dtype == a.dtype): 

7997 return a 

7998 return masked_array(a, dtype=dtype, copy=False, keep_mask=True, subok=True) 

7999 

8000 

8001############################################################################## 

8002# Pickling # 

8003############################################################################## 

8004 

8005def _pickle_warn(method): 

8006 # NumPy 1.15.0, 2017-12-10 

8007 warnings.warn( 

8008 f"np.ma.{method} is deprecated, use pickle.{method} instead", 

8009 DeprecationWarning, stacklevel=3) 

8010 

8011 

8012def fromfile(file, dtype=float, count=-1, sep=''): 

8013 raise NotImplementedError( 

8014 "fromfile() not yet implemented for a MaskedArray.") 

8015 

8016 

8017def fromflex(fxarray): 

8018 """ 

8019 Build a masked array from a suitable flexible-type array. 

8020 

8021 The input array has to have a data-type with ``_data`` and ``_mask`` 

8022 fields. This type of array is output by `MaskedArray.toflex`. 

8023 

8024 Parameters 

8025 ---------- 

8026 fxarray : ndarray 

8027 The structured input array, containing ``_data`` and ``_mask`` 

8028 fields. If present, other fields are discarded. 

8029 

8030 Returns 

8031 ------- 

8032 result : MaskedArray 

8033 The constructed masked array. 

8034 

8035 See Also 

8036 -------- 

8037 MaskedArray.toflex : Build a flexible-type array from a masked array. 

8038 

8039 Examples 

8040 -------- 

8041 >>> x = np.ma.array(np.arange(9).reshape(3, 3), mask=[0] + [1, 0] * 4) 

8042 >>> rec = x.toflex() 

8043 >>> rec 

8044 array([[(0, False), (1, True), (2, False)], 

8045 [(3, True), (4, False), (5, True)], 

8046 [(6, False), (7, True), (8, False)]], 

8047 dtype=[('_data', '<i8'), ('_mask', '?')]) 

8048 >>> x2 = np.ma.fromflex(rec) 

8049 >>> x2 

8050 masked_array( 

8051 data=[[0, --, 2], 

8052 [--, 4, --], 

8053 [6, --, 8]], 

8054 mask=[[False, True, False], 

8055 [ True, False, True], 

8056 [False, True, False]], 

8057 fill_value=999999) 

8058 

8059 Extra fields can be present in the structured array but are discarded: 

8060 

8061 >>> dt = [('_data', '<i4'), ('_mask', '|b1'), ('field3', '<f4')] 

8062 >>> rec2 = np.zeros((2, 2), dtype=dt) 

8063 >>> rec2 

8064 array([[(0, False, 0.), (0, False, 0.)], 

8065 [(0, False, 0.), (0, False, 0.)]], 

8066 dtype=[('_data', '<i4'), ('_mask', '?'), ('field3', '<f4')]) 

8067 >>> y = np.ma.fromflex(rec2) 

8068 >>> y 

8069 masked_array( 

8070 data=[[0, 0], 

8071 [0, 0]], 

8072 mask=[[False, False], 

8073 [False, False]], 

8074 fill_value=999999, 

8075 dtype=int32) 

8076 

8077 """ 

8078 return masked_array(fxarray['_data'], mask=fxarray['_mask']) 

8079 

8080 

8081class _convert2ma: 

8082 

8083 """ 

8084 Convert functions from numpy to numpy.ma. 

8085 

8086 Parameters 

8087 ---------- 

8088 _methodname : string 

8089 Name of the method to transform. 

8090 

8091 """ 

8092 __doc__ = None 

8093 

8094 def __init__(self, funcname, params=None): 

8095 self._func = getattr(np, funcname) 

8096 self.__doc__ = self.getdoc() 

8097 self._extras = params or {} 

8098 

8099 def getdoc(self): 

8100 "Return the doc of the function (from the doc of the method)." 

8101 doc = getattr(self._func, '__doc__', None) 

8102 sig = get_object_signature(self._func) 

8103 if doc: 

8104 # Add the signature of the function at the beginning of the doc 

8105 if sig: 

8106 sig = "%s%s\n" % (self._func.__name__, sig) 

8107 doc = sig + doc 

8108 return doc 

8109 

8110 def __call__(self, *args, **params): 

8111 # Find the common parameters to the call and the definition 

8112 _extras = self._extras 

8113 common_params = set(params).intersection(_extras) 

8114 # Drop the common parameters from the call 

8115 for p in common_params: 

8116 _extras[p] = params.pop(p) 

8117 # Get the result 

8118 result = self._func.__call__(*args, **params).view(MaskedArray) 

8119 if "fill_value" in common_params: 

8120 result.fill_value = _extras.get("fill_value", None) 

8121 if "hardmask" in common_params: 

8122 result._hardmask = bool(_extras.get("hard_mask", False)) 

8123 return result 

8124 

8125arange = _convert2ma('arange', params=dict(fill_value=None, hardmask=False)) 

8126clip = np.clip 

8127diff = np.diff 

8128empty = _convert2ma('empty', params=dict(fill_value=None, hardmask=False)) 

8129empty_like = _convert2ma('empty_like') 

8130frombuffer = _convert2ma('frombuffer') 

8131fromfunction = _convert2ma('fromfunction') 

8132identity = _convert2ma( 

8133 'identity', params=dict(fill_value=None, hardmask=False)) 

8134indices = np.indices 

8135ones = _convert2ma('ones', params=dict(fill_value=None, hardmask=False)) 

8136ones_like = np.ones_like 

8137squeeze = np.squeeze 

8138zeros = _convert2ma('zeros', params=dict(fill_value=None, hardmask=False)) 

8139zeros_like = np.zeros_like 

8140 

8141 

8142def append(a, b, axis=None): 

8143 """Append values to the end of an array. 

8144 

8145 .. versionadded:: 1.9.0 

8146 

8147 Parameters 

8148 ---------- 

8149 a : array_like 

8150 Values are appended to a copy of this array. 

8151 b : array_like 

8152 These values are appended to a copy of `a`. It must be of the 

8153 correct shape (the same shape as `a`, excluding `axis`). If `axis` 

8154 is not specified, `b` can be any shape and will be flattened 

8155 before use. 

8156 axis : int, optional 

8157 The axis along which `v` are appended. If `axis` is not given, 

8158 both `a` and `b` are flattened before use. 

8159 

8160 Returns 

8161 ------- 

8162 append : MaskedArray 

8163 A copy of `a` with `b` appended to `axis`. Note that `append` 

8164 does not occur in-place: a new array is allocated and filled. If 

8165 `axis` is None, the result is a flattened array. 

8166 

8167 See Also 

8168 -------- 

8169 numpy.append : Equivalent function in the top-level NumPy module. 

8170 

8171 Examples 

8172 -------- 

8173 >>> import numpy.ma as ma 

8174 >>> a = ma.masked_values([1, 2, 3], 2) 

8175 >>> b = ma.masked_values([[4, 5, 6], [7, 8, 9]], 7) 

8176 >>> ma.append(a, b) 

8177 masked_array(data=[1, --, 3, 4, 5, 6, --, 8, 9], 

8178 mask=[False, True, False, False, False, False, True, False, 

8179 False], 

8180 fill_value=999999) 

8181 """ 

8182 return concatenate([a, b], axis)