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

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

2425 statements  

1""" 

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

3 

4This package was initially written for numarray by Paul F. Dubois 

5at Lawrence Livermore National Laboratory. 

6In 2006, the package was completely rewritten by Pierre Gerard-Marchant 

7(University of Georgia) to make the MaskedArray class a subclass of ndarray, 

8and to improve support of structured arrays. 

9 

10 

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

12Released for unlimited redistribution. 

13 

14* Adapted for numpy_core 2005 by Travis Oliphant and (mainly) Paul Dubois. 

15* Subclassing of the base `ndarray` 2006 by Pierre Gerard-Marchant 

16 (pgmdevlist_AT_gmail_DOT_com) 

17* Improvements suggested by Reggie Dugard (reggie_AT_merfinllc_DOT_com) 

18 

19.. moduleauthor:: Pierre Gerard-Marchant 

20 

21""" 

22# pylint: disable-msg=E1002 

23import builtins 

24import inspect 

25import operator 

26import warnings 

27import textwrap 

28import re 

29from functools import reduce 

30 

31import numpy as np 

32import numpy.core.umath as umath 

33import numpy.core.numerictypes as ntypes 

34from numpy.core import multiarray as mu 

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

36from numpy import array as narray 

37from numpy.lib.function_base import angle 

38from numpy.compat import ( 

39 getargspec, formatargspec, long, unicode, bytes 

40 ) 

41from numpy import expand_dims 

42from numpy.core.numeric import normalize_axis_tuple 

43 

44 

45__all__ = [ 

46 'MAError', 'MaskError', 'MaskType', 'MaskedArray', 'abs', 'absolute', 

47 'add', 'all', 'allclose', 'allequal', 'alltrue', 'amax', 'amin', 

48 'angle', 'anom', 'anomalies', 'any', 'append', 'arange', 'arccos', 

49 'arccosh', 'arcsin', 'arcsinh', 'arctan', 'arctan2', 'arctanh', 

50 'argmax', 'argmin', 'argsort', 'around', 'array', 'asanyarray', 

51 'asarray', 'bitwise_and', 'bitwise_or', 'bitwise_xor', 'bool_', 'ceil', 

52 'choose', 'clip', 'common_fill_value', 'compress', 'compressed', 

53 'concatenate', 'conjugate', 'convolve', 'copy', 'correlate', 'cos', 'cosh', 

54 'count', 'cumprod', 'cumsum', 'default_fill_value', 'diag', 'diagonal', 

55 'diff', 'divide', 'empty', 'empty_like', 'equal', 'exp', 

56 'expand_dims', 'fabs', 'filled', 'fix_invalid', 'flatten_mask', 

57 'flatten_structured_array', 'floor', 'floor_divide', 'fmod', 

58 'frombuffer', 'fromflex', 'fromfunction', 'getdata', 'getmask', 

59 'getmaskarray', 'greater', 'greater_equal', 'harden_mask', 'hypot', 

60 'identity', 'ids', 'indices', 'inner', 'innerproduct', 'isMA', 

61 'isMaskedArray', 'is_mask', 'is_masked', 'isarray', 'left_shift', 

62 'less', 'less_equal', 'log', 'log10', 'log2', 

63 'logical_and', 'logical_not', 'logical_or', 'logical_xor', 'make_mask', 

64 'make_mask_descr', 'make_mask_none', 'mask_or', 'masked', 

65 'masked_array', 'masked_equal', 'masked_greater', 

66 'masked_greater_equal', 'masked_inside', 'masked_invalid', 

67 'masked_less', 'masked_less_equal', 'masked_not_equal', 

68 'masked_object', 'masked_outside', 'masked_print_option', 

69 'masked_singleton', 'masked_values', 'masked_where', 'max', 'maximum', 

70 'maximum_fill_value', 'mean', 'min', 'minimum', 'minimum_fill_value', 

71 'mod', 'multiply', 'mvoid', 'ndim', 'negative', 'nomask', 'nonzero', 

72 'not_equal', 'ones', 'ones_like', 'outer', 'outerproduct', 'power', 'prod', 

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

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

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

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

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

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

79 ] 

80 

81MaskType = np.bool_ 

82nomask = MaskType(0) 

83 

84class MaskedArrayFutureWarning(FutureWarning): 

85 pass 

86 

87def _deprecate_argsort_axis(arr): 

88 """ 

89 Adjust the axis passed to argsort, warning if necessary 

90 

91 Parameters 

92 ---------- 

93 arr 

94 The array which argsort was called on 

95 

96 np.ma.argsort has a long-term bug where the default of the axis argument 

97 is wrong (gh-8701), which now must be kept for backwards compatibility. 

98 Thankfully, this only makes a difference when arrays are 2- or more- 

99 dimensional, so we only need a warning then. 

100 """ 

101 if arr.ndim <= 1: 

102 # no warning needed - but switch to -1 anyway, to avoid surprising 

103 # subclasses, which are more likely to implement scalar axes. 

104 return -1 

105 else: 

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

107 warnings.warn( 

108 "In the future the default for argsort will be axis=-1, not the " 

109 "current None, to match its documentation and np.argsort. " 

110 "Explicitly pass -1 or None to silence this warning.", 

111 MaskedArrayFutureWarning, stacklevel=3) 

112 return None 

113 

114 

115def doc_note(initialdoc, note): 

116 """ 

117 Adds a Notes section to an existing docstring. 

118 

119 """ 

120 if initialdoc is None: 

121 return 

122 if note is None: 

123 return initialdoc 

124 

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

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

127 

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

129 

130 

131def get_object_signature(obj): 

132 """ 

133 Get the signature from obj 

134 

135 """ 

136 try: 

137 sig = formatargspec(*getargspec(obj)) 

138 except TypeError: 

139 sig = '' 

140 return sig 

141 

142 

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

144# Exceptions # 

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

146 

147 

148class MAError(Exception): 

149 """ 

150 Class for masked array related errors. 

151 

152 """ 

153 pass 

154 

155 

156class MaskError(MAError): 

157 """ 

158 Class for mask related errors. 

159 

160 """ 

161 pass 

162 

163 

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

165# Filling options # 

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

167 

168 

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

170default_filler = {'b': True, 

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

172 'f': 1.e20, 

173 'i': 999999, 

174 'O': '?', 

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

176 'u': 999999, 

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

178 'U': 'N/A' 

179 } 

180 

181# Add datetime64 and timedelta64 types 

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

183 "fs", "as"]: 

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

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

186 

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

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

189max_filler = ntypes._minvals 

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

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

192 

193min_filler = ntypes._maxvals 

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

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

196 

197del float_types_list 

198 

199def _recursive_fill_value(dtype, f): 

200 """ 

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

202 """ 

203 if dtype.names is not None: 

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

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

206 # for int8. 

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

208 vals = tuple( 

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

210 for name in dtype.names) 

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

212 elif dtype.subdtype: 

213 subtype, shape = dtype.subdtype 

214 subval = _recursive_fill_value(subtype, f) 

215 return np.full(shape, subval) 

216 else: 

217 return f(dtype) 

218 

219 

220def _get_dtype_of(obj): 

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

222 if isinstance(obj, np.dtype): 

223 return obj 

224 elif hasattr(obj, 'dtype'): 

225 return obj.dtype 

226 else: 

227 return np.asanyarray(obj).dtype 

228 

229 

230def default_fill_value(obj): 

231 """ 

232 Return the default fill value for the argument object. 

233 

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

235 array or the type of the input scalar: 

236 

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

238 datatype default 

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

240 bool True 

241 int 999999 

242 float 1.e20 

243 complex 1.e20+0j 

244 object '?' 

245 string 'N/A' 

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

247 

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

249 default fill value for its type. 

250 

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

252 the default scalar fill value. 

253 

254 Parameters 

255 ---------- 

256 obj : ndarray, dtype or scalar 

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

258 is returned. 

259 

260 Returns 

261 ------- 

262 fill_value : scalar 

263 The default fill value. 

264 

265 Examples 

266 -------- 

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

268 999999 

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

270 1e+20 

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

272 (1e+20+0j) 

273 

274 """ 

275 def _scalar_fill_value(dtype): 

276 if dtype.kind in 'Mm': 

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

278 else: 

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

280 

281 dtype = _get_dtype_of(obj) 

282 return _recursive_fill_value(dtype, _scalar_fill_value) 

283 

284 

285def _extremum_fill_value(obj, extremum, extremum_name): 

286 

287 def _scalar_fill_value(dtype): 

288 try: 

289 return extremum[dtype] 

290 except KeyError as e: 

291 raise TypeError( 

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

293 ) from None 

294 

295 dtype = _get_dtype_of(obj) 

296 return _recursive_fill_value(dtype, _scalar_fill_value) 

297 

298 

299def minimum_fill_value(obj): 

300 """ 

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

302 

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

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

305 

306 Parameters 

307 ---------- 

308 obj : ndarray, dtype or scalar 

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

310 

311 Returns 

312 ------- 

313 val : scalar 

314 The maximum representable value. 

315 

316 Raises 

317 ------ 

318 TypeError 

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

320 

321 See Also 

322 -------- 

323 maximum_fill_value : The inverse function. 

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

325 MaskedArray.fill_value : Return current fill value. 

326 

327 Examples 

328 -------- 

329 >>> import numpy.ma as ma 

330 >>> a = np.int8() 

331 >>> ma.minimum_fill_value(a) 

332 127 

333 >>> a = np.int32() 

334 >>> ma.minimum_fill_value(a) 

335 2147483647 

336 

337 An array of numeric data can also be passed. 

338 

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

340 >>> ma.minimum_fill_value(a) 

341 127 

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

343 >>> ma.minimum_fill_value(a) 

344 inf 

345 

346 """ 

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

348 

349 

350def maximum_fill_value(obj): 

351 """ 

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

353 

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

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

356 

357 Parameters 

358 ---------- 

359 obj : ndarray, dtype or scalar 

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

361 

362 Returns 

363 ------- 

364 val : scalar 

365 The minimum representable value. 

366 

367 Raises 

368 ------ 

369 TypeError 

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

371 

372 See Also 

373 -------- 

374 minimum_fill_value : The inverse function. 

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

376 MaskedArray.fill_value : Return current fill value. 

377 

378 Examples 

379 -------- 

380 >>> import numpy.ma as ma 

381 >>> a = np.int8() 

382 >>> ma.maximum_fill_value(a) 

383 -128 

384 >>> a = np.int32() 

385 >>> ma.maximum_fill_value(a) 

386 -2147483648 

387 

388 An array of numeric data can also be passed. 

389 

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

391 >>> ma.maximum_fill_value(a) 

392 -128 

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

394 >>> ma.maximum_fill_value(a) 

395 -inf 

396 

397 """ 

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

399 

400 

401def _recursive_set_fill_value(fillvalue, dt): 

402 """ 

403 Create a fill value for a structured dtype. 

404 

405 Parameters 

406 ---------- 

407 fillvalue : scalar or array_like 

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

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

410 dt : dtype 

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

412 

413 Returns 

414 ------- 

415 val : tuple 

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

417 

418 """ 

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

420 output_value = [] 

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

422 cdtype = dt[name] 

423 if cdtype.subdtype: 

424 cdtype = cdtype.subdtype[0] 

425 

426 if cdtype.names is not None: 

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

428 else: 

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

430 return tuple(output_value) 

431 

432 

433def _check_fill_value(fill_value, ndtype): 

434 """ 

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

436 

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

438 

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

440 

441 The result is always a 0d array. 

442 

443 """ 

444 ndtype = np.dtype(ndtype) 

445 if fill_value is None: 

446 fill_value = default_fill_value(ndtype) 

447 elif ndtype.names is not None: 

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

449 try: 

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

451 except ValueError as e: 

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

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

454 else: 

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

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

457 dtype=ndtype) 

458 else: 

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

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

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

462 raise TypeError(err_msg % ndtype) 

463 else: 

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

465 # Also in case of converting string arrays. 

466 try: 

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

468 except (OverflowError, ValueError) as e: 

469 # Raise TypeError instead of OverflowError or ValueError. 

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

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

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

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

474 return np.array(fill_value) 

475 

476 

477def set_fill_value(a, fill_value): 

478 """ 

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

480 

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

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

483 doing anything. 

484 

485 Parameters 

486 ---------- 

487 a : array_like 

488 Input array. 

489 fill_value : dtype 

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

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

492 

493 Returns 

494 ------- 

495 None 

496 Nothing returned by this function. 

497 

498 See Also 

499 -------- 

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

501 MaskedArray.fill_value : Return current fill value. 

502 MaskedArray.set_fill_value : Equivalent method. 

503 

504 Examples 

505 -------- 

506 >>> import numpy.ma as ma 

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

508 >>> a 

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

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

511 >>> a 

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

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

514 fill_value=999999) 

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

516 >>> a 

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

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

519 fill_value=-999) 

520 

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

522 

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

524 >>> a 

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

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

527 >>> a 

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

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

530 >>> a 

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

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

533 >>> a 

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

535 

536 """ 

537 if isinstance(a, MaskedArray): 

538 a.set_fill_value(fill_value) 

539 return 

540 

541 

542def get_fill_value(a): 

543 """ 

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

545 default filling value for that type. 

546 

547 """ 

548 if isinstance(a, MaskedArray): 

549 result = a.fill_value 

550 else: 

551 result = default_fill_value(a) 

552 return result 

553 

554 

555def common_fill_value(a, b): 

556 """ 

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

558 

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

560 otherwise return None. 

561 

562 Parameters 

563 ---------- 

564 a, b : MaskedArray 

565 The masked arrays for which to compare fill values. 

566 

567 Returns 

568 ------- 

569 fill_value : scalar or None 

570 The common fill value, or None. 

571 

572 Examples 

573 -------- 

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

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

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

577 3.0 

578 

579 """ 

580 t1 = get_fill_value(a) 

581 t2 = get_fill_value(b) 

582 if t1 == t2: 

583 return t1 

584 return None 

585 

586 

587def filled(a, fill_value=None): 

588 """ 

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

590 

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

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

593 ``a.fill_value``. 

594 

595 Parameters 

596 ---------- 

597 a : MaskedArray or array_like 

598 An input object. 

599 fill_value : array_like, optional. 

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

601 resulting filled array should be broadcastable 

602 over input array. Default is None. 

603 

604 Returns 

605 ------- 

606 a : ndarray 

607 The filled array. 

608 

609 See Also 

610 -------- 

611 compressed 

612 

613 Examples 

614 -------- 

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

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

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

618 >>> x.filled() 

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

620 [999999, 4, 5], 

621 [ 6, 7, 8]]) 

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

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

624 [333, 4, 5], 

625 [ 6, 7, 8]]) 

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

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

628 [0, 4, 5], 

629 [6, 7, 8]]) 

630 

631 """ 

632 if hasattr(a, 'filled'): 

633 return a.filled(fill_value) 

634 

635 elif isinstance(a, ndarray): 

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

637 return a 

638 elif isinstance(a, dict): 

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

640 else: 

641 return np.array(a) 

642 

643 

644def get_masked_subclass(*arrays): 

645 """ 

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

647 

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

649 

650 """ 

651 if len(arrays) == 1: 

652 arr = arrays[0] 

653 if isinstance(arr, MaskedArray): 

654 rcls = type(arr) 

655 else: 

656 rcls = MaskedArray 

657 else: 

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

659 rcls = arrcls[0] 

660 if not issubclass(rcls, MaskedArray): 

661 rcls = MaskedArray 

662 for cls in arrcls[1:]: 

663 if issubclass(cls, rcls): 

664 rcls = cls 

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

666 if rcls.__name__ == 'MaskedConstant': 

667 return MaskedArray 

668 return rcls 

669 

670 

671def getdata(a, subok=True): 

672 """ 

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

674 

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

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

677 

678 Parameters 

679 ---------- 

680 a : array_like 

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

682 subok : bool 

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

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

685 

686 See Also 

687 -------- 

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

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

690 

691 Examples 

692 -------- 

693 >>> import numpy.ma as ma 

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

695 >>> a 

696 masked_array( 

697 data=[[1, --], 

698 [3, 4]], 

699 mask=[[False, True], 

700 [False, False]], 

701 fill_value=2) 

702 >>> ma.getdata(a) 

703 array([[1, 2], 

704 [3, 4]]) 

705 

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

707 

708 >>> a.data 

709 array([[1, 2], 

710 [3, 4]]) 

711 

712 """ 

713 try: 

714 data = a._data 

715 except AttributeError: 

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

717 if not subok: 

718 return data.view(ndarray) 

719 return data 

720 

721 

722get_data = getdata 

723 

724 

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

726 """ 

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

728 

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

730 

731 Parameters 

732 ---------- 

733 a : array_like 

734 Input array, a (subclass of) ndarray. 

735 mask : sequence, optional 

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

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

738 copy : bool, optional 

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

740 Default is True. 

741 fill_value : scalar, optional 

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

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

744 

745 Returns 

746 ------- 

747 b : MaskedArray 

748 The input array with invalid entries fixed. 

749 

750 Notes 

751 ----- 

752 A copy is performed by default. 

753 

754 Examples 

755 -------- 

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

757 >>> x 

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

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

760 fill_value=1e+20) 

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

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

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

764 fill_value=1e+20) 

765 

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

767 >>> fixed.data 

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

769 >>> x.data 

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

771 

772 """ 

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

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

775 if not invalid.any(): 

776 return a 

777 a._mask |= invalid 

778 if fill_value is None: 

779 fill_value = a.fill_value 

780 a._data[invalid] = fill_value 

781 return a 

782 

783def is_string_or_list_of_strings(val): 

784 return (isinstance(val, str) or 

785 (isinstance(val, list) and val and 

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

787 

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

789# Ufuncs # 

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

791 

792 

793ufunc_domain = {} 

794ufunc_fills = {} 

795 

796 

797class _DomainCheckInterval: 

798 """ 

799 Define a valid interval, so that : 

800 

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

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

803 

804 """ 

805 

806 def __init__(self, a, b): 

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

808 if a > b: 

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

810 self.a = a 

811 self.b = b 

812 

813 def __call__(self, x): 

814 "Execute the call behavior." 

815 # nans at masked positions cause RuntimeWarnings, even though 

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

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

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

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

820 

821 

822class _DomainTan: 

823 """ 

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

825 

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

827 

828 """ 

829 

830 def __init__(self, eps): 

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

832 self.eps = eps 

833 

834 def __call__(self, x): 

835 "Executes the call behavior." 

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

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

838 

839 

840class _DomainSafeDivide: 

841 """ 

842 Define a domain for safe division. 

843 

844 """ 

845 

846 def __init__(self, tolerance=None): 

847 self.tolerance = tolerance 

848 

849 def __call__(self, a, b): 

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

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

852 # component of numpy's import time. 

853 if self.tolerance is None: 

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

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

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

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

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

859 

860 

861class _DomainGreater: 

862 """ 

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

864 

865 """ 

866 

867 def __init__(self, critical_value): 

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

869 self.critical_value = critical_value 

870 

871 def __call__(self, x): 

872 "Executes the call behavior." 

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

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

875 

876 

877class _DomainGreaterEqual: 

878 """ 

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

880 

881 """ 

882 

883 def __init__(self, critical_value): 

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

885 self.critical_value = critical_value 

886 

887 def __call__(self, x): 

888 "Executes the call behavior." 

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

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

891 

892 

893class _MaskedUFunc: 

894 def __init__(self, ufunc): 

895 self.f = ufunc 

896 self.__doc__ = ufunc.__doc__ 

897 self.__name__ = ufunc.__name__ 

898 

899 def __str__(self): 

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

901 

902 

903class _MaskedUnaryOperation(_MaskedUFunc): 

904 """ 

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

906 pre-masked. 

907 

908 Parameters 

909 ---------- 

910 mufunc : callable 

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

912 as ``_MaskedUnaryOperation.f``. 

913 fill : scalar, optional 

914 Filling value, default is 0. 

915 domain : class instance 

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

917 classes. Default is None. 

918 

919 """ 

920 

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

922 super().__init__(mufunc) 

923 self.fill = fill 

924 self.domain = domain 

925 ufunc_domain[mufunc] = domain 

926 ufunc_fills[mufunc] = fill 

927 

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

929 """ 

930 Execute the call behavior. 

931 

932 """ 

933 d = getdata(a) 

934 # Deal with domain 

935 if self.domain is not None: 

936 # Case 1.1. : Domained function 

937 # nans at masked positions cause RuntimeWarnings, even though 

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

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

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

941 # Make a mask 

942 m = ~umath.isfinite(result) 

943 m |= self.domain(d) 

944 m |= getmask(a) 

945 else: 

946 # Case 1.2. : Function without a domain 

947 # Get the result and the mask 

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

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

950 m = getmask(a) 

951 

952 if not result.ndim: 

953 # Case 2.1. : The result is scalarscalar 

954 if m: 

955 return masked 

956 return result 

957 

958 if m is not nomask: 

959 # Case 2.2. The result is an array 

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

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

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

963 

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

965 # equal) 

966 try: 

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

968 except TypeError: 

969 pass 

970 # Transform to 

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

972 masked_result._mask = m 

973 masked_result._update_from(a) 

974 return masked_result 

975 

976 

977class _MaskedBinaryOperation(_MaskedUFunc): 

978 """ 

979 Define masked version of binary operations, where invalid 

980 values are pre-masked. 

981 

982 Parameters 

983 ---------- 

984 mbfunc : function 

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

986 as ``_MaskedBinaryOperation.f``. 

987 domain : class instance 

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

989 classes. Default is None. 

990 fillx : scalar, optional 

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

992 filly : scalar, optional 

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

994 

995 """ 

996 

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

998 """ 

999 abfunc(fillx, filly) must be defined. 

1000 

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

1002 

1003 """ 

1004 super().__init__(mbfunc) 

1005 self.fillx = fillx 

1006 self.filly = filly 

1007 ufunc_domain[mbfunc] = None 

1008 ufunc_fills[mbfunc] = (fillx, filly) 

1009 

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

1011 """ 

1012 Execute the call behavior. 

1013 

1014 """ 

1015 # Get the data, as ndarray 

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

1017 # Get the result 

1018 with np.errstate(): 

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

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

1021 # Get the mask for the result 

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

1023 if ma is nomask: 

1024 if mb is nomask: 

1025 m = nomask 

1026 else: 

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

1028 elif mb is nomask: 

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

1030 else: 

1031 m = umath.logical_or(ma, mb) 

1032 

1033 # Case 1. : scalar 

1034 if not result.ndim: 

1035 if m: 

1036 return masked 

1037 return result 

1038 

1039 # Case 2. : array 

1040 # Revert result to da where masked 

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

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

1043 try: 

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

1045 except Exception: 

1046 pass 

1047 

1048 # Transforms to a (subclass of) MaskedArray 

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

1050 masked_result._mask = m 

1051 if isinstance(a, MaskedArray): 

1052 masked_result._update_from(a) 

1053 elif isinstance(b, MaskedArray): 

1054 masked_result._update_from(b) 

1055 return masked_result 

1056 

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

1058 """ 

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

1060 

1061 """ 

1062 tclass = get_masked_subclass(target) 

1063 m = getmask(target) 

1064 t = filled(target, self.filly) 

1065 if t.shape == (): 

1066 t = t.reshape(1) 

1067 if m is not nomask: 

1068 m = make_mask(m, copy=True) 

1069 m.shape = (1,) 

1070 

1071 if m is nomask: 

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

1073 mr = nomask 

1074 else: 

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

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

1077 

1078 if not tr.shape: 

1079 if mr: 

1080 return masked 

1081 else: 

1082 return tr 

1083 masked_tr = tr.view(tclass) 

1084 masked_tr._mask = mr 

1085 return masked_tr 

1086 

1087 def outer(self, a, b): 

1088 """ 

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

1090 

1091 """ 

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

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

1094 ma = getmask(a) 

1095 mb = getmask(b) 

1096 if ma is nomask and mb is nomask: 

1097 m = nomask 

1098 else: 

1099 ma = getmaskarray(a) 

1100 mb = getmaskarray(b) 

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

1102 if (not m.ndim) and m: 

1103 return masked 

1104 if m is not nomask: 

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

1106 if not d.shape: 

1107 return d 

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

1109 masked_d._mask = m 

1110 return masked_d 

1111 

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

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

1114 value. 

1115 

1116 """ 

1117 tclass = get_masked_subclass(target) 

1118 t = filled(target, self.filly) 

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

1120 masked_result = result.view(tclass) 

1121 return masked_result 

1122 

1123 

1124 

1125class _DomainedBinaryOperation(_MaskedUFunc): 

1126 """ 

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

1128 

1129 They have no reduce, outer or accumulate. 

1130 

1131 Parameters 

1132 ---------- 

1133 mbfunc : function 

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

1135 as ``_DomainedBinaryOperation.f``. 

1136 domain : class instance 

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

1138 classes. 

1139 fillx : scalar, optional 

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

1141 filly : scalar, optional 

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

1143 

1144 """ 

1145 

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

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

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

1149 """ 

1150 super().__init__(dbfunc) 

1151 self.domain = domain 

1152 self.fillx = fillx 

1153 self.filly = filly 

1154 ufunc_domain[dbfunc] = domain 

1155 ufunc_fills[dbfunc] = (fillx, filly) 

1156 

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

1158 "Execute the call behavior." 

1159 # Get the data 

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

1161 # Get the result 

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

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

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

1165 m = ~umath.isfinite(result) 

1166 m |= getmask(a) 

1167 m |= getmask(b) 

1168 # Apply the domain 

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

1170 if domain is not None: 

1171 m |= domain(da, db) 

1172 # Take care of the scalar case first 

1173 if not m.ndim: 

1174 if m: 

1175 return masked 

1176 else: 

1177 return result 

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

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

1180 try: 

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

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

1183 masked_da = umath.multiply(m, da) 

1184 # only add back if it can be cast safely 

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

1186 result += masked_da 

1187 except Exception: 

1188 pass 

1189 

1190 # Transforms to a (subclass of) MaskedArray 

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

1192 masked_result._mask = m 

1193 if isinstance(a, MaskedArray): 

1194 masked_result._update_from(a) 

1195 elif isinstance(b, MaskedArray): 

1196 masked_result._update_from(b) 

1197 return masked_result 

1198 

1199 

1200# Unary ufuncs 

1201exp = _MaskedUnaryOperation(umath.exp) 

1202conjugate = _MaskedUnaryOperation(umath.conjugate) 

1203sin = _MaskedUnaryOperation(umath.sin) 

1204cos = _MaskedUnaryOperation(umath.cos) 

1205arctan = _MaskedUnaryOperation(umath.arctan) 

1206arcsinh = _MaskedUnaryOperation(umath.arcsinh) 

1207sinh = _MaskedUnaryOperation(umath.sinh) 

1208cosh = _MaskedUnaryOperation(umath.cosh) 

1209tanh = _MaskedUnaryOperation(umath.tanh) 

1210abs = absolute = _MaskedUnaryOperation(umath.absolute) 

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

1212fabs = _MaskedUnaryOperation(umath.fabs) 

1213negative = _MaskedUnaryOperation(umath.negative) 

1214floor = _MaskedUnaryOperation(umath.floor) 

1215ceil = _MaskedUnaryOperation(umath.ceil) 

1216around = _MaskedUnaryOperation(np.round_) 

1217logical_not = _MaskedUnaryOperation(umath.logical_not) 

1218 

1219# Domained unary ufuncs 

1220sqrt = _MaskedUnaryOperation(umath.sqrt, 0.0, 

1221 _DomainGreaterEqual(0.0)) 

1222log = _MaskedUnaryOperation(umath.log, 1.0, 

1223 _DomainGreater(0.0)) 

1224log2 = _MaskedUnaryOperation(umath.log2, 1.0, 

1225 _DomainGreater(0.0)) 

1226log10 = _MaskedUnaryOperation(umath.log10, 1.0, 

1227 _DomainGreater(0.0)) 

1228tan = _MaskedUnaryOperation(umath.tan, 0.0, 

1229 _DomainTan(1e-35)) 

1230arcsin = _MaskedUnaryOperation(umath.arcsin, 0.0, 

1231 _DomainCheckInterval(-1.0, 1.0)) 

1232arccos = _MaskedUnaryOperation(umath.arccos, 0.0, 

1233 _DomainCheckInterval(-1.0, 1.0)) 

1234arccosh = _MaskedUnaryOperation(umath.arccosh, 1.0, 

1235 _DomainGreaterEqual(1.0)) 

1236arctanh = _MaskedUnaryOperation(umath.arctanh, 0.0, 

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

1238 

1239# Binary ufuncs 

1240add = _MaskedBinaryOperation(umath.add) 

1241subtract = _MaskedBinaryOperation(umath.subtract) 

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

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

1244equal = _MaskedBinaryOperation(umath.equal) 

1245equal.reduce = None 

1246not_equal = _MaskedBinaryOperation(umath.not_equal) 

1247not_equal.reduce = None 

1248less_equal = _MaskedBinaryOperation(umath.less_equal) 

1249less_equal.reduce = None 

1250greater_equal = _MaskedBinaryOperation(umath.greater_equal) 

1251greater_equal.reduce = None 

1252less = _MaskedBinaryOperation(umath.less) 

1253less.reduce = None 

1254greater = _MaskedBinaryOperation(umath.greater) 

1255greater.reduce = None 

1256logical_and = _MaskedBinaryOperation(umath.logical_and) 

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

1258logical_or = _MaskedBinaryOperation(umath.logical_or) 

1259sometrue = logical_or.reduce 

1260logical_xor = _MaskedBinaryOperation(umath.logical_xor) 

1261bitwise_and = _MaskedBinaryOperation(umath.bitwise_and) 

1262bitwise_or = _MaskedBinaryOperation(umath.bitwise_or) 

1263bitwise_xor = _MaskedBinaryOperation(umath.bitwise_xor) 

1264hypot = _MaskedBinaryOperation(umath.hypot) 

1265 

1266# Domained binary ufuncs 

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

1268true_divide = _DomainedBinaryOperation(umath.true_divide, 

1269 _DomainSafeDivide(), 0, 1) 

1270floor_divide = _DomainedBinaryOperation(umath.floor_divide, 

1271 _DomainSafeDivide(), 0, 1) 

1272remainder = _DomainedBinaryOperation(umath.remainder, 

1273 _DomainSafeDivide(), 0, 1) 

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

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

1276 

1277 

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

1279# Mask creation functions # 

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

1281 

1282 

1283def _replace_dtype_fields_recursive(dtype, primitive_dtype): 

1284 "Private function allowing recursion in _replace_dtype_fields." 

1285 _recurse = _replace_dtype_fields_recursive 

1286 

1287 # Do we have some name fields ? 

1288 if dtype.names is not None: 

1289 descr = [] 

1290 for name in dtype.names: 

1291 field = dtype.fields[name] 

1292 if len(field) == 3: 

1293 # Prepend the title to the name 

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

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

1296 new_dtype = np.dtype(descr) 

1297 

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

1299 elif dtype.subdtype: 

1300 descr = list(dtype.subdtype) 

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

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

1303 

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

1305 else: 

1306 new_dtype = primitive_dtype 

1307 

1308 # preserve identity of dtypes 

1309 if new_dtype == dtype: 

1310 new_dtype = dtype 

1311 

1312 return new_dtype 

1313 

1314 

1315def _replace_dtype_fields(dtype, primitive_dtype): 

1316 """ 

1317 Construct a dtype description list from a given dtype. 

1318 

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

1320 recursively replaced with `primitive_dtype`. 

1321 

1322 Arguments are coerced to dtypes first. 

1323 """ 

1324 dtype = np.dtype(dtype) 

1325 primitive_dtype = np.dtype(primitive_dtype) 

1326 return _replace_dtype_fields_recursive(dtype, primitive_dtype) 

1327 

1328 

1329def make_mask_descr(ndtype): 

1330 """ 

1331 Construct a dtype description list from a given dtype. 

1332 

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

1334 boolean type. Field names are not altered. 

1335 

1336 Parameters 

1337 ---------- 

1338 ndtype : dtype 

1339 The dtype to convert. 

1340 

1341 Returns 

1342 ------- 

1343 result : dtype 

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

1345 

1346 Examples 

1347 -------- 

1348 >>> import numpy.ma as ma 

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

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

1351 >>> dtype 

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

1353 >>> ma.make_mask_descr(dtype) 

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

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

1356 dtype('bool') 

1357 

1358 """ 

1359 return _replace_dtype_fields(ndtype, MaskType) 

1360 

1361 

1362def getmask(a): 

1363 """ 

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

1365 

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

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

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

1369 

1370 Parameters 

1371 ---------- 

1372 a : array_like 

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

1374 

1375 See Also 

1376 -------- 

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

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

1379 

1380 Examples 

1381 -------- 

1382 >>> import numpy.ma as ma 

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

1384 >>> a 

1385 masked_array( 

1386 data=[[1, --], 

1387 [3, 4]], 

1388 mask=[[False, True], 

1389 [False, False]], 

1390 fill_value=2) 

1391 >>> ma.getmask(a) 

1392 array([[False, True], 

1393 [False, False]]) 

1394 

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

1396 

1397 >>> a.mask 

1398 array([[False, True], 

1399 [False, False]]) 

1400 

1401 Result when mask == `nomask` 

1402 

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

1404 >>> b 

1405 masked_array( 

1406 data=[[1, 2], 

1407 [3, 4]], 

1408 mask=False, 

1409 fill_value=999999) 

1410 >>> ma.nomask 

1411 False 

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

1413 True 

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

1415 True 

1416 

1417 """ 

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

1419 

1420 

1421get_mask = getmask 

1422 

1423 

1424def getmaskarray(arr): 

1425 """ 

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

1427 

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

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

1430 the same shape as `arr`. 

1431 

1432 Parameters 

1433 ---------- 

1434 arr : array_like 

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

1436 

1437 See Also 

1438 -------- 

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

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

1441 

1442 Examples 

1443 -------- 

1444 >>> import numpy.ma as ma 

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

1446 >>> a 

1447 masked_array( 

1448 data=[[1, --], 

1449 [3, 4]], 

1450 mask=[[False, True], 

1451 [False, False]], 

1452 fill_value=2) 

1453 >>> ma.getmaskarray(a) 

1454 array([[False, True], 

1455 [False, False]]) 

1456 

1457 Result when mask == ``nomask`` 

1458 

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

1460 >>> b 

1461 masked_array( 

1462 data=[[1, 2], 

1463 [3, 4]], 

1464 mask=False, 

1465 fill_value=999999) 

1466 >>> ma.getmaskarray(b) 

1467 array([[False, False], 

1468 [False, False]]) 

1469 

1470 """ 

1471 mask = getmask(arr) 

1472 if mask is nomask: 

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

1474 return mask 

1475 

1476 

1477def is_mask(m): 

1478 """ 

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

1480 

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

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

1483 mask has a flexible dtype. 

1484 

1485 Parameters 

1486 ---------- 

1487 m : array_like 

1488 Array to test. 

1489 

1490 Returns 

1491 ------- 

1492 result : bool 

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

1494 

1495 See Also 

1496 -------- 

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

1498 

1499 Examples 

1500 -------- 

1501 >>> import numpy.ma as ma 

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

1503 >>> m 

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

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

1506 fill_value=0) 

1507 >>> ma.is_mask(m) 

1508 False 

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

1510 True 

1511 

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

1513 for it to be considered a valid mask. 

1514 

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

1516 >>> ma.is_mask(m) 

1517 False 

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

1519 >>> m 

1520 array([False, True, False]) 

1521 >>> ma.is_mask(m) 

1522 True 

1523 

1524 Arrays with complex dtypes don't return True. 

1525 

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

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

1528 >>> dtype 

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

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

1531 ... dtype=dtype) 

1532 >>> m 

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

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

1535 >>> ma.is_mask(m) 

1536 False 

1537 

1538 """ 

1539 try: 

1540 return m.dtype.type is MaskType 

1541 except AttributeError: 

1542 return False 

1543 

1544 

1545def _shrink_mask(m): 

1546 """ 

1547 Shrink a mask to nomask if possible 

1548 """ 

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

1550 return nomask 

1551 else: 

1552 return m 

1553 

1554 

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

1556 """ 

1557 Create a boolean mask from an array. 

1558 

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

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

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

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

1563 

1564 Parameters 

1565 ---------- 

1566 m : array_like 

1567 Potential mask. 

1568 copy : bool, optional 

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

1570 shrink : bool, optional 

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

1572 dtype : dtype, optional 

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

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

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

1576 case ``nomask`` is always returned. 

1577 

1578 Returns 

1579 ------- 

1580 result : ndarray 

1581 A boolean mask derived from `m`. 

1582 

1583 Examples 

1584 -------- 

1585 >>> import numpy.ma as ma 

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

1587 >>> ma.make_mask(m) 

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

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

1590 >>> ma.make_mask(m) 

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

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

1593 >>> ma.make_mask(m) 

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

1595 

1596 Effect of the `shrink` parameter. 

1597 

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

1599 >>> m 

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

1601 >>> ma.make_mask(m) 

1602 False 

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

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

1605 

1606 Using a flexible `dtype`. 

1607 

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

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

1610 >>> arr = [] 

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

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

1613 >>> arr 

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

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

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

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

1618 >>> arr 

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

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

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

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

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

1624 

1625 """ 

1626 if m is nomask: 

1627 return nomask 

1628 

1629 # Make sure the input dtype is valid. 

1630 dtype = make_mask_descr(dtype) 

1631 

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

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

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

1635 

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

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

1638 # Bas les masques ! 

1639 if shrink: 

1640 result = _shrink_mask(result) 

1641 return result 

1642 

1643 

1644def make_mask_none(newshape, dtype=None): 

1645 """ 

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

1647 

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

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

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

1651 

1652 Parameters 

1653 ---------- 

1654 newshape : tuple 

1655 A tuple indicating the shape of the mask. 

1656 dtype : {None, dtype}, optional 

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

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

1659 

1660 Returns 

1661 ------- 

1662 result : ndarray 

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

1664 

1665 See Also 

1666 -------- 

1667 make_mask : Create a boolean mask from an array. 

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

1669 

1670 Examples 

1671 -------- 

1672 >>> import numpy.ma as ma 

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

1674 array([False, False, False]) 

1675 

1676 Defining a more complex dtype. 

1677 

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

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

1680 >>> dtype 

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

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

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

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

1685 

1686 """ 

1687 if dtype is None: 

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

1689 else: 

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

1691 return result 

1692 

1693 

1694def _recursive_mask_or(m1, m2, newmask): 

1695 names = m1.dtype.names 

1696 for name in names: 

1697 current1 = m1[name] 

1698 if current1.dtype.names is not None: 

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

1700 else: 

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

1702 

1703 

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

1705 """ 

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

1707 

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

1709 (i.e. False). 

1710 

1711 Parameters 

1712 ---------- 

1713 m1, m2 : array_like 

1714 Input masks. 

1715 copy : bool, optional 

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

1717 of the other input mask. Defaults to False. 

1718 shrink : bool, optional 

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

1720 False. Defaults to True. 

1721 

1722 Returns 

1723 ------- 

1724 mask : output mask 

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

1726 

1727 Raises 

1728 ------ 

1729 ValueError 

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

1731 

1732 Examples 

1733 -------- 

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

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

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

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

1738 

1739 """ 

1740 

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

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

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

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

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

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

1747 if m1 is m2 and is_mask(m1): 

1748 return m1 

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

1750 if dtype1 != dtype2: 

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

1752 if dtype1.names is not None: 

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

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

1755 _recursive_mask_or(m1, m2, newmask) 

1756 return newmask 

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

1758 

1759 

1760def flatten_mask(mask): 

1761 """ 

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

1763 are collapsed. 

1764 

1765 Parameters 

1766 ---------- 

1767 mask : array_like 

1768 Input array, which will be interpreted as booleans. 

1769 

1770 Returns 

1771 ------- 

1772 flattened_mask : ndarray of bools 

1773 The flattened input. 

1774 

1775 Examples 

1776 -------- 

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

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

1779 array([False, False, True]) 

1780 

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

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

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

1784 

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

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

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

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

1789 

1790 """ 

1791 

1792 def _flatmask(mask): 

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

1794 mnames = mask.dtype.names 

1795 if mnames is not None: 

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

1797 else: 

1798 return mask 

1799 

1800 def _flatsequence(sequence): 

1801 "Generates a flattened version of the sequence." 

1802 try: 

1803 for element in sequence: 

1804 if hasattr(element, '__iter__'): 

1805 yield from _flatsequence(element) 

1806 else: 

1807 yield element 

1808 except TypeError: 

1809 yield sequence 

1810 

1811 mask = np.asarray(mask) 

1812 flattened = _flatsequence(_flatmask(mask)) 

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

1814 

1815 

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

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

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

1819 if mask is not nomask: 

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

1821 return nomask 

1822 

1823 

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

1825# Masking functions # 

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

1827 

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

1829 """ 

1830 Mask an array where a condition is met. 

1831 

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

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

1834 

1835 Parameters 

1836 ---------- 

1837 condition : array_like 

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

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

1840 a : array_like 

1841 Array to mask. 

1842 copy : bool 

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

1844 `a` in place and return a view. 

1845 

1846 Returns 

1847 ------- 

1848 result : MaskedArray 

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

1850 

1851 See Also 

1852 -------- 

1853 masked_values : Mask using floating point equality. 

1854 masked_equal : Mask where equal to a given value. 

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

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

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

1858 masked_less : Mask where less than a given value. 

1859 masked_greater : Mask where greater than a given value. 

1860 masked_inside : Mask inside a given interval. 

1861 masked_outside : Mask outside a given interval. 

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

1863 

1864 Examples 

1865 -------- 

1866 >>> import numpy.ma as ma 

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

1868 >>> a 

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

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

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

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

1873 fill_value=999999) 

1874 

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

1876 

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

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

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

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

1881 fill_value='N/A', 

1882 dtype='<U1') 

1883 

1884 Effect of the `copy` argument. 

1885 

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

1887 >>> c 

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

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

1890 fill_value=999999) 

1891 >>> c[0] = 99 

1892 >>> c 

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

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

1895 fill_value=999999) 

1896 >>> a 

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

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

1899 >>> c[0] = 99 

1900 >>> c 

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

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

1903 fill_value=999999) 

1904 >>> a 

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

1906 

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

1908 

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

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

1911 >>> a 

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

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

1914 fill_value=999999) 

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

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

1917 >>> b 

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

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

1920 fill_value=999999) 

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

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

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

1924 fill_value=999999) 

1925 

1926 """ 

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

1928 cond = make_mask(condition, shrink=False) 

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

1930 

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

1932 if cshape and cshape != ashape: 

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

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

1935 if hasattr(a, '_mask'): 

1936 cond = mask_or(cond, a._mask) 

1937 cls = type(a) 

1938 else: 

1939 cls = MaskedArray 

1940 result = a.view(cls) 

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

1942 result.mask = _shrink_mask(cond) 

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

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

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

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

1947 return result 

1948 

1949 

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

1951 """ 

1952 Mask an array where greater than a given value. 

1953 

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

1955 `condition` = (x > value). 

1956 

1957 See Also 

1958 -------- 

1959 masked_where : Mask where a condition is met. 

1960 

1961 Examples 

1962 -------- 

1963 >>> import numpy.ma as ma 

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

1965 >>> a 

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

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

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

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

1970 fill_value=999999) 

1971 

1972 """ 

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

1974 

1975 

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

1977 """ 

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

1979 

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

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

1982 

1983 See Also 

1984 -------- 

1985 masked_where : Mask where a condition is met. 

1986 

1987 Examples 

1988 -------- 

1989 >>> import numpy.ma as ma 

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

1991 >>> a 

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

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

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

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

1996 fill_value=999999) 

1997 

1998 """ 

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

2000 

2001 

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

2003 """ 

2004 Mask an array where less than a given value. 

2005 

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

2007 `condition` = (x < value). 

2008 

2009 See Also 

2010 -------- 

2011 masked_where : Mask where a condition is met. 

2012 

2013 Examples 

2014 -------- 

2015 >>> import numpy.ma as ma 

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

2017 >>> a 

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

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

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

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

2022 fill_value=999999) 

2023 

2024 """ 

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

2026 

2027 

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

2029 """ 

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

2031 

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

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

2034 

2035 See Also 

2036 -------- 

2037 masked_where : Mask where a condition is met. 

2038 

2039 Examples 

2040 -------- 

2041 >>> import numpy.ma as ma 

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

2043 >>> a 

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

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

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

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

2048 fill_value=999999) 

2049 

2050 """ 

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

2052 

2053 

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

2055 """ 

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

2057 

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

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

2060 

2061 See Also 

2062 -------- 

2063 masked_where : Mask where a condition is met. 

2064 

2065 Examples 

2066 -------- 

2067 >>> import numpy.ma as ma 

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

2069 >>> a 

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

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

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

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

2074 fill_value=999999) 

2075 

2076 """ 

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

2078 

2079 

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

2081 """ 

2082 Mask an array where equal to a given value. 

2083 

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

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

2086 is set to `value`. 

2087 

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

2089 

2090 See Also 

2091 -------- 

2092 masked_where : Mask where a condition is met. 

2093 masked_values : Mask using floating point equality. 

2094 

2095 Examples 

2096 -------- 

2097 >>> import numpy.ma as ma 

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

2099 >>> a 

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

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

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

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

2104 fill_value=2) 

2105 

2106 """ 

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

2108 output.fill_value = value 

2109 return output 

2110 

2111 

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

2113 """ 

2114 Mask an array inside a given interval. 

2115 

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

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

2118 can be given in either order. 

2119 

2120 See Also 

2121 -------- 

2122 masked_where : Mask where a condition is met. 

2123 

2124 Notes 

2125 ----- 

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

2127 

2128 Examples 

2129 -------- 

2130 >>> import numpy.ma as ma 

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

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

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

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

2135 fill_value=1e+20) 

2136 

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

2138 

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

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

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

2142 fill_value=1e+20) 

2143 

2144 """ 

2145 if v2 < v1: 

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

2147 xf = filled(x) 

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

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

2150 

2151 

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

2153 """ 

2154 Mask an array outside a given interval. 

2155 

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

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

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

2159 

2160 See Also 

2161 -------- 

2162 masked_where : Mask where a condition is met. 

2163 

2164 Notes 

2165 ----- 

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

2167 

2168 Examples 

2169 -------- 

2170 >>> import numpy.ma as ma 

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

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

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

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

2175 fill_value=1e+20) 

2176 

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

2178 

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

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

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

2182 fill_value=1e+20) 

2183 

2184 """ 

2185 if v2 < v1: 

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

2187 xf = filled(x) 

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

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

2190 

2191 

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

2193 """ 

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

2195 

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

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

2198 

2199 Parameters 

2200 ---------- 

2201 x : array_like 

2202 Array to mask 

2203 value : object 

2204 Comparison value 

2205 copy : {True, False}, optional 

2206 Whether to return a copy of `x`. 

2207 shrink : {True, False}, optional 

2208 Whether to collapse a mask full of False to nomask 

2209 

2210 Returns 

2211 ------- 

2212 result : MaskedArray 

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

2214 

2215 See Also 

2216 -------- 

2217 masked_where : Mask where a condition is met. 

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

2219 masked_values : Mask using floating point equality. 

2220 

2221 Examples 

2222 -------- 

2223 >>> import numpy.ma as ma 

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

2225 >>> # don't eat spoiled food 

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

2227 >>> eat 

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

2229 mask=[ True, False], 

2230 fill_value='green_eggs', 

2231 dtype=object) 

2232 >>> # plain ol` ham is boring 

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

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

2235 >>> eat 

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

2237 mask=False, 

2238 fill_value='green_eggs', 

2239 dtype=object) 

2240 

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

2242 

2243 >>> eat 

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

2245 mask=False, 

2246 fill_value='green_eggs', 

2247 dtype=object) 

2248 

2249 """ 

2250 if isMaskedArray(x): 

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

2252 mask = x._mask 

2253 else: 

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

2255 mask = nomask 

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

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

2258 

2259 

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

2261 """ 

2262 Mask using floating point equality. 

2263 

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

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

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

2267 

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

2269 `masked_equal`. 

2270 

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

2272 possible. 

2273 

2274 Parameters 

2275 ---------- 

2276 x : array_like 

2277 Array to mask. 

2278 value : float 

2279 Masking value. 

2280 rtol, atol : float, optional 

2281 Tolerance parameters passed on to `isclose` 

2282 copy : bool, optional 

2283 Whether to return a copy of `x`. 

2284 shrink : bool, optional 

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

2286 

2287 Returns 

2288 ------- 

2289 result : MaskedArray 

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

2291 

2292 See Also 

2293 -------- 

2294 masked_where : Mask where a condition is met. 

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

2296 

2297 Examples 

2298 -------- 

2299 >>> import numpy.ma as ma 

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

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

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

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

2304 fill_value=1.1) 

2305 

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

2307 

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

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

2310 mask=False, 

2311 fill_value=2.1) 

2312 

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

2314 

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

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

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

2318 fill_value=2.1) 

2319 

2320 """ 

2321 xnew = filled(x, value) 

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

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

2324 else: 

2325 mask = umath.equal(xnew, value) 

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

2327 if shrink: 

2328 ret.shrink_mask() 

2329 return ret 

2330 

2331 

2332def masked_invalid(a, copy=True): 

2333 """ 

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

2335 

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

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

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

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

2340 

2341 See Also 

2342 -------- 

2343 masked_where : Mask where a condition is met. 

2344 

2345 Examples 

2346 -------- 

2347 >>> import numpy.ma as ma 

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

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

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

2351 >>> a 

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

2353 >>> ma.masked_invalid(a) 

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

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

2356 fill_value=1e+20) 

2357 

2358 """ 

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

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

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

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

2363 if res._mask is nomask: 

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

2365 return res 

2366 

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

2368# Printing options # 

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

2370 

2371 

2372class _MaskedPrintOption: 

2373 """ 

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

2375 

2376 """ 

2377 

2378 def __init__(self, display): 

2379 """ 

2380 Create the masked_print_option object. 

2381 

2382 """ 

2383 self._display = display 

2384 self._enabled = True 

2385 

2386 def display(self): 

2387 """ 

2388 Display the string to print for masked values. 

2389 

2390 """ 

2391 return self._display 

2392 

2393 def set_display(self, s): 

2394 """ 

2395 Set the string to print for masked values. 

2396 

2397 """ 

2398 self._display = s 

2399 

2400 def enabled(self): 

2401 """ 

2402 Is the use of the display value enabled? 

2403 

2404 """ 

2405 return self._enabled 

2406 

2407 def enable(self, shrink=1): 

2408 """ 

2409 Set the enabling shrink to `shrink`. 

2410 

2411 """ 

2412 self._enabled = shrink 

2413 

2414 def __str__(self): 

2415 return str(self._display) 

2416 

2417 __repr__ = __str__ 

2418 

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

2420masked_print_option = _MaskedPrintOption('--') 

2421 

2422 

2423def _recursive_printoption(result, mask, printopt): 

2424 """ 

2425 Puts printoptions in result where mask is True. 

2426 

2427 Private function allowing for recursion 

2428 

2429 """ 

2430 names = result.dtype.names 

2431 if names is not None: 

2432 for name in names: 

2433 curdata = result[name] 

2434 curmask = mask[name] 

2435 _recursive_printoption(curdata, curmask, printopt) 

2436 else: 

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

2438 return 

2439 

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

2441_legacy_print_templates = dict( 

2442 long_std=textwrap.dedent("""\ 

2443 masked_%(name)s(data = 

2444 %(data)s, 

2445 %(nlen)s mask = 

2446 %(mask)s, 

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

2448 """), 

2449 long_flx=textwrap.dedent("""\ 

2450 masked_%(name)s(data = 

2451 %(data)s, 

2452 %(nlen)s mask = 

2453 %(mask)s, 

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

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

2456 """), 

2457 short_std=textwrap.dedent("""\ 

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

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

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

2461 """), 

2462 short_flx=textwrap.dedent("""\ 

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

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

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

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

2467 """) 

2468) 

2469 

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

2471# MaskedArray class # 

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

2473 

2474 

2475def _recursive_filled(a, mask, fill_value): 

2476 """ 

2477 Recursively fill `a` with `fill_value`. 

2478 

2479 """ 

2480 names = a.dtype.names 

2481 for name in names: 

2482 current = a[name] 

2483 if current.dtype.names is not None: 

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

2485 else: 

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

2487 

2488 

2489def flatten_structured_array(a): 

2490 """ 

2491 Flatten a structured array. 

2492 

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

2494 (nested) fields. 

2495 

2496 Parameters 

2497 ---------- 

2498 a : structured array 

2499 

2500 Returns 

2501 ------- 

2502 output : masked array or ndarray 

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

2504 standard ndarray. 

2505 

2506 Examples 

2507 -------- 

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

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

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

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

2512 [2., 2.]]) 

2513 

2514 """ 

2515 

2516 def flatten_sequence(iterable): 

2517 """ 

2518 Flattens a compound of nested iterables. 

2519 

2520 """ 

2521 for elm in iter(iterable): 

2522 if hasattr(elm, '__iter__'): 

2523 yield from flatten_sequence(elm) 

2524 else: 

2525 yield elm 

2526 

2527 a = np.asanyarray(a) 

2528 inishape = a.shape 

2529 a = a.ravel() 

2530 if isinstance(a, MaskedArray): 

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

2532 out = out.view(MaskedArray) 

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

2534 for d in getmaskarray(a)]) 

2535 else: 

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

2537 if len(inishape) > 1: 

2538 newshape = list(out.shape) 

2539 newshape[0] = inishape 

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

2541 return out 

2542 

2543 

2544def _arraymethod(funcname, onmask=True): 

2545 """ 

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

2547 

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

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

2550 on the original ``_data``. 

2551 

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

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

2554 to the initial mask. 

2555 

2556 Parameters 

2557 ---------- 

2558 funcname : str 

2559 Name of the function to apply on data. 

2560 onmask : bool 

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

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

2563 attribute. 

2564 

2565 Returns 

2566 ------- 

2567 method : instancemethod 

2568 Class method wrapper of the specified basic array method. 

2569 

2570 """ 

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

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

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

2574 result._update_from(self) 

2575 mask = self._mask 

2576 if not onmask: 

2577 result.__setmask__(mask) 

2578 elif mask is not nomask: 

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

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

2581 return result 

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

2583 if methdoc is not None: 

2584 wrapped_method.__doc__ = methdoc.__doc__ 

2585 wrapped_method.__name__ = funcname 

2586 return wrapped_method 

2587 

2588 

2589class MaskedIterator: 

2590 """ 

2591 Flat iterator object to iterate over masked arrays. 

2592 

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

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

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

2596 

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

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

2599 advanced indexing. 

2600 

2601 See Also 

2602 -------- 

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

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

2605 

2606 Notes 

2607 ----- 

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

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

2610 

2611 Examples 

2612 -------- 

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

2614 >>> fl = x.flat 

2615 >>> type(fl) 

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

2617 >>> for item in fl: 

2618 ... print(item) 

2619 ... 

2620 0 

2621 1 

2622 2 

2623 3 

2624 4 

2625 5 

2626 

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

2628 returns a masked array: 

2629 

2630 >>> fl[2:4] 

2631 masked_array(data = [2 3], 

2632 mask = False, 

2633 fill_value = 999999) 

2634 

2635 """ 

2636 

2637 def __init__(self, ma): 

2638 self.ma = ma 

2639 self.dataiter = ma._data.flat 

2640 

2641 if ma._mask is nomask: 

2642 self.maskiter = None 

2643 else: 

2644 self.maskiter = ma._mask.flat 

2645 

2646 def __iter__(self): 

2647 return self 

2648 

2649 def __getitem__(self, indx): 

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

2651 if self.maskiter is not None: 

2652 _mask = self.maskiter.__getitem__(indx) 

2653 if isinstance(_mask, ndarray): 

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

2655 _mask.shape = result.shape 

2656 result._mask = _mask 

2657 elif isinstance(_mask, np.void): 

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

2659 elif _mask: # Just a scalar, masked 

2660 return masked 

2661 return result 

2662 

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

2664 def __setitem__(self, index, value): 

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

2666 if self.maskiter is not None: 

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

2668 

2669 def __next__(self): 

2670 """ 

2671 Return the next value, or raise StopIteration. 

2672 

2673 Examples 

2674 -------- 

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

2676 >>> fl = x.flat 

2677 >>> next(fl) 

2678 3 

2679 >>> next(fl) 

2680 masked 

2681 >>> next(fl) 

2682 Traceback (most recent call last): 

2683 ... 

2684 StopIteration 

2685 

2686 """ 

2687 d = next(self.dataiter) 

2688 if self.maskiter is not None: 

2689 m = next(self.maskiter) 

2690 if isinstance(m, np.void): 

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

2692 elif m: # Just a scalar, masked 

2693 return masked 

2694 return d 

2695 

2696 

2697class MaskedArray(ndarray): 

2698 """ 

2699 An array class with possibly masked values. 

2700 

2701 Masked values of True exclude the corresponding element from any 

2702 computation. 

2703 

2704 Construction:: 

2705 

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

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

2708 shrink=True, order=None) 

2709 

2710 Parameters 

2711 ---------- 

2712 data : array_like 

2713 Input data. 

2714 mask : sequence, optional 

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

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

2717 dtype : dtype, optional 

2718 Data type of the output. 

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

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

2721 a copy is performed. 

2722 copy : bool, optional 

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

2724 Default is False. 

2725 subok : bool, optional 

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

2727 plain `MaskedArray`. Default is True. 

2728 ndmin : int, optional 

2729 Minimum number of dimensions. Default is 0. 

2730 fill_value : scalar, optional 

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

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

2733 keep_mask : bool, optional 

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

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

2736 hard_mask : bool, optional 

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

2738 cannot be unmasked. Default is False. 

2739 shrink : bool, optional 

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

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

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

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

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

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

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

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

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

2749 

2750 Examples 

2751 -------- 

2752 

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

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

2755 

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

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

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

2759 masked_array( 

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

2761 [3, 4, --]], 

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

2763 [False, False, True]], 

2764 fill_value=999999) 

2765 

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

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

2768 boolean value: 

2769 

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

2771 masked_array( 

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

2773 [3, 4, 5]], 

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

2775 [False, False, False]], 

2776 fill_value=999999) 

2777 

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

2779 masked_array( 

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

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

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

2783 [ True, True, True]], 

2784 fill_value=999999, 

2785 dtype=int64) 

2786 

2787 .. note:: 

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

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

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

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

2792 

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

2794 True 

2795 

2796 """ 

2797 

2798 __array_priority__ = 15 

2799 _defaultmask = nomask 

2800 _defaulthardmask = False 

2801 _baseclass = ndarray 

2802 

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

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

2805 _print_width = 100 

2806 _print_width_1d = 1500 

2807 

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

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

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

2811 """ 

2812 Create a new masked array from scratch. 

2813 

2814 Notes 

2815 ----- 

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

2817 

2818 """ 

2819 # Process data. 

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

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

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

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

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

2825 copy = True 

2826 

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

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

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

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

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

2832 else: 

2833 _data = ndarray.view(_data, cls) 

2834 

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

2836 # still has the _mask attribute like MaskedArrays 

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

2838 _data._mask = data._mask 

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

2840 # Process mask. 

2841 # Type of the mask 

2842 mdtype = make_mask_descr(_data.dtype) 

2843 

2844 if mask is nomask: 

2845 # Case 1. : no mask in input. 

2846 # Erase the current mask ? 

2847 if not keep_mask: 

2848 # With a reduced version 

2849 if shrink: 

2850 _data._mask = nomask 

2851 # With full version 

2852 else: 

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

2854 # Check whether we missed something 

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

2856 try: 

2857 # If data is a sequence of masked array 

2858 mask = np.array( 

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

2860 for m in data], dtype=mdtype) 

2861 except ValueError: 

2862 # If data is nested 

2863 mask = nomask 

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

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

2866 _data._mask = mask 

2867 _data._sharedmask = False 

2868 else: 

2869 _data._sharedmask = not copy 

2870 if copy: 

2871 _data._mask = _data._mask.copy() 

2872 # Reset the shape of the original mask 

2873 if getmask(data) is not nomask: 

2874 data._mask.shape = data.shape 

2875 else: 

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

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

2878 if mask is True and mdtype == MaskType: 

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

2880 elif mask is False and mdtype == MaskType: 

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

2882 else: 

2883 # Read the mask with the current mdtype 

2884 try: 

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

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

2887 except TypeError: 

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

2889 dtype=mdtype) 

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

2891 if mask.shape != _data.shape: 

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

2893 if nm == 1: 

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

2895 elif nm == nd: 

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

2897 else: 

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

2899 "mask size is %i." 

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

2901 copy = True 

2902 # Set the mask to the new value 

2903 if _data._mask is nomask: 

2904 _data._mask = mask 

2905 _data._sharedmask = not copy 

2906 else: 

2907 if not keep_mask: 

2908 _data._mask = mask 

2909 _data._sharedmask = not copy 

2910 else: 

2911 if _data.dtype.names is not None: 

2912 def _recursive_or(a, b): 

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

2914 for name in a.dtype.names: 

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

2916 if af.dtype.names is not None: 

2917 _recursive_or(af, bf) 

2918 else: 

2919 af |= bf 

2920 

2921 _recursive_or(_data._mask, mask) 

2922 else: 

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

2924 _data._sharedmask = False 

2925 # Update fill_value. 

2926 if fill_value is None: 

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

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

2929 if fill_value is not None: 

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

2931 # Process extra options .. 

2932 if hard_mask is None: 

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

2934 else: 

2935 _data._hardmask = hard_mask 

2936 _data._baseclass = _baseclass 

2937 return _data 

2938 

2939 

2940 def _update_from(self, obj): 

2941 """ 

2942 Copies some attributes of obj to self. 

2943 

2944 """ 

2945 if isinstance(obj, ndarray): 

2946 _baseclass = type(obj) 

2947 else: 

2948 _baseclass = ndarray 

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

2950 _optinfo = {} 

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

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

2953 if not isinstance(obj, MaskedArray): 

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

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

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

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

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

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

2960 _optinfo=_optinfo, 

2961 _basedict=_optinfo) 

2962 self.__dict__.update(_dict) 

2963 self.__dict__.update(_optinfo) 

2964 return 

2965 

2966 def __array_finalize__(self, obj): 

2967 """ 

2968 Finalizes the masked array. 

2969 

2970 """ 

2971 # Get main attributes. 

2972 self._update_from(obj) 

2973 

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

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

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

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

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

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

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

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

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

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

2984 # most users think that np.empty_like(marr) -- which goes via this 

2985 # method -- should return a masked array with an empty mask (see 

2986 # gh-3404 and linked discussions), but others disagree, and they have 

2987 # existing code which depends on empty_like returning an array that 

2988 # matches the input mask. 

2989 # 

2990 # Historically our algorithm was: if the template object mask had the 

2991 # same *number of elements* as us, then we used *it's mask object 

2992 # itself* as our mask, so that writes to us would also write to the 

2993 # original array. This is horribly broken in multiple ways. 

2994 # 

2995 # Now what we do instead is, if the template object mask has the same 

2996 # number of elements as us, and we do not have the same base pointer 

2997 # as the template object (b/c views like arr[...] should keep the same 

2998 # mask), then we make a copy of the template object mask and use 

2999 # that. This is also horribly broken but somewhat less so. Maybe. 

3000 if isinstance(obj, ndarray): 

3001 # XX: This looks like a bug -- shouldn't it check self.dtype 

3002 # instead? 

3003 if obj.dtype.names is not None: 

3004 _mask = getmaskarray(obj) 

3005 else: 

3006 _mask = getmask(obj) 

3007 

3008 # If self and obj point to exactly the same data, then probably 

3009 # self is a simple view of obj (e.g., self = obj[...]), so they 

3010 # should share the same mask. (This isn't 100% reliable, e.g. self 

3011 # could be the first row of obj, or have strange strides, but as a 

3012 # heuristic it's not bad.) In all other cases, we make a copy of 

3013 # the mask, so that future modifications to 'self' do not end up 

3014 # side-effecting 'obj' as well. 

3015 if (_mask is not nomask and obj.__array_interface__["data"][0] 

3016 != self.__array_interface__["data"][0]): 

3017 # We should make a copy. But we could get here via astype, 

3018 # in which case the mask might need a new dtype as well 

3019 # (e.g., changing to or from a structured dtype), and the 

3020 # order could have changed. So, change the mask type if 

3021 # needed and use astype instead of copy. 

3022 if self.dtype == obj.dtype: 

3023 _mask_dtype = _mask.dtype 

3024 else: 

3025 _mask_dtype = make_mask_descr(self.dtype) 

3026 

3027 if self.flags.c_contiguous: 

3028 order = "C" 

3029 elif self.flags.f_contiguous: 

3030 order = "F" 

3031 else: 

3032 order = "K" 

3033 

3034 _mask = _mask.astype(_mask_dtype, order) 

3035 else: 

3036 # Take a view so shape changes, etc., do not propagate back. 

3037 _mask = _mask.view() 

3038 else: 

3039 _mask = nomask 

3040 

3041 self._mask = _mask 

3042 # Finalize the mask 

3043 if self._mask is not nomask: 

3044 try: 

3045 self._mask.shape = self.shape 

3046 except ValueError: 

3047 self._mask = nomask 

3048 except (TypeError, AttributeError): 

3049 # When _mask.shape is not writable (because it's a void) 

3050 pass 

3051 

3052 # Finalize the fill_value 

3053 if self._fill_value is not None: 

3054 self._fill_value = _check_fill_value(self._fill_value, self.dtype) 

3055 elif self.dtype.names is not None: 

3056 # Finalize the default fill_value for structured arrays 

3057 self._fill_value = _check_fill_value(None, self.dtype) 

3058 

3059 def __array_wrap__(self, obj, context=None): 

3060 """ 

3061 Special hook for ufuncs. 

3062 

3063 Wraps the numpy array and sets the mask according to context. 

3064 

3065 """ 

3066 if obj is self: # for in-place operations 

3067 result = obj 

3068 else: 

3069 result = obj.view(type(self)) 

3070 result._update_from(self) 

3071 

3072 if context is not None: 

3073 result._mask = result._mask.copy() 

3074 func, args, out_i = context 

3075 # args sometimes contains outputs (gh-10459), which we don't want 

3076 input_args = args[:func.nin] 

3077 m = reduce(mask_or, [getmaskarray(arg) for arg in input_args]) 

3078 # Get the domain mask 

3079 domain = ufunc_domain.get(func, None) 

3080 if domain is not None: 

3081 # Take the domain, and make sure it's a ndarray 

3082 with np.errstate(divide='ignore', invalid='ignore'): 

3083 d = filled(domain(*input_args), True) 

3084 

3085 if d.any(): 

3086 # Fill the result where the domain is wrong 

3087 try: 

3088 # Binary domain: take the last value 

3089 fill_value = ufunc_fills[func][-1] 

3090 except TypeError: 

3091 # Unary domain: just use this one 

3092 fill_value = ufunc_fills[func] 

3093 except KeyError: 

3094 # Domain not recognized, use fill_value instead 

3095 fill_value = self.fill_value 

3096 

3097 np.copyto(result, fill_value, where=d) 

3098 

3099 # Update the mask 

3100 if m is nomask: 

3101 m = d 

3102 else: 

3103 # Don't modify inplace, we risk back-propagation 

3104 m = (m | d) 

3105 

3106 # Make sure the mask has the proper size 

3107 if result is not self and result.shape == () and m: 

3108 return masked 

3109 else: 

3110 result._mask = m 

3111 result._sharedmask = False 

3112 

3113 return result 

3114 

3115 def view(self, dtype=None, type=None, fill_value=None): 

3116 """ 

3117 Return a view of the MaskedArray data. 

3118 

3119 Parameters 

3120 ---------- 

3121 dtype : data-type or ndarray sub-class, optional 

3122 Data-type descriptor of the returned view, e.g., float32 or int16. 

3123 The default, None, results in the view having the same data-type 

3124 as `a`. As with ``ndarray.view``, dtype can also be specified as 

3125 an ndarray sub-class, which then specifies the type of the 

3126 returned object (this is equivalent to setting the ``type`` 

3127 parameter). 

3128 type : Python type, optional 

3129 Type of the returned view, either ndarray or a subclass. The 

3130 default None results in type preservation. 

3131 fill_value : scalar, optional 

3132 The value to use for invalid entries (None by default). 

3133 If None, then this argument is inferred from the passed `dtype`, or 

3134 in its absence the original array, as discussed in the notes below. 

3135 

3136 See Also 

3137 -------- 

3138 numpy.ndarray.view : Equivalent method on ndarray object. 

3139 

3140 Notes 

3141 ----- 

3142 

3143 ``a.view()`` is used two different ways: 

3144 

3145 ``a.view(some_dtype)`` or ``a.view(dtype=some_dtype)`` constructs a view 

3146 of the array's memory with a different data-type. This can cause a 

3147 reinterpretation of the bytes of memory. 

3148 

3149 ``a.view(ndarray_subclass)`` or ``a.view(type=ndarray_subclass)`` just 

3150 returns an instance of `ndarray_subclass` that looks at the same array 

3151 (same shape, dtype, etc.) This does not cause a reinterpretation of the 

3152 memory. 

3153 

3154 If `fill_value` is not specified, but `dtype` is specified (and is not 

3155 an ndarray sub-class), the `fill_value` of the MaskedArray will be 

3156 reset. If neither `fill_value` nor `dtype` are specified (or if 

3157 `dtype` is an ndarray sub-class), then the fill value is preserved. 

3158 Finally, if `fill_value` is specified, but `dtype` is not, the fill 

3159 value is set to the specified value. 

3160 

3161 For ``a.view(some_dtype)``, if ``some_dtype`` has a different number of 

3162 bytes per entry than the previous dtype (for example, converting a 

3163 regular array to a structured array), then the behavior of the view 

3164 cannot be predicted just from the superficial appearance of ``a`` (shown 

3165 by ``print(a)``). It also depends on exactly how ``a`` is stored in 

3166 memory. Therefore if ``a`` is C-ordered versus fortran-ordered, versus 

3167 defined as a slice or transpose, etc., the view may give different 

3168 results. 

3169 """ 

3170 

3171 if dtype is None: 

3172 if type is None: 

3173 output = ndarray.view(self) 

3174 else: 

3175 output = ndarray.view(self, type) 

3176 elif type is None: 

3177 try: 

3178 if issubclass(dtype, ndarray): 

3179 output = ndarray.view(self, dtype) 

3180 dtype = None 

3181 else: 

3182 output = ndarray.view(self, dtype) 

3183 except TypeError: 

3184 output = ndarray.view(self, dtype) 

3185 else: 

3186 output = ndarray.view(self, dtype, type) 

3187 

3188 # also make the mask be a view (so attr changes to the view's 

3189 # mask do no affect original object's mask) 

3190 # (especially important to avoid affecting np.masked singleton) 

3191 if getmask(output) is not nomask: 

3192 output._mask = output._mask.view() 

3193 

3194 # Make sure to reset the _fill_value if needed 

3195 if getattr(output, '_fill_value', None) is not None: 

3196 if fill_value is None: 

3197 if dtype is None: 

3198 pass # leave _fill_value as is 

3199 else: 

3200 output._fill_value = None 

3201 else: 

3202 output.fill_value = fill_value 

3203 return output 

3204 

3205 def __getitem__(self, indx): 

3206 """ 

3207 x.__getitem__(y) <==> x[y] 

3208 

3209 Return the item described by i, as a masked array. 

3210 

3211 """ 

3212 # We could directly use ndarray.__getitem__ on self. 

3213 # But then we would have to modify __array_finalize__ to prevent the 

3214 # mask of being reshaped if it hasn't been set up properly yet 

3215 # So it's easier to stick to the current version 

3216 dout = self.data[indx] 

3217 _mask = self._mask 

3218 

3219 def _is_scalar(m): 

3220 return not isinstance(m, np.ndarray) 

3221 

3222 def _scalar_heuristic(arr, elem): 

3223 """ 

3224 Return whether `elem` is a scalar result of indexing `arr`, or None 

3225 if undecidable without promoting nomask to a full mask 

3226 """ 

3227 # obviously a scalar 

3228 if not isinstance(elem, np.ndarray): 

3229 return True 

3230 

3231 # object array scalar indexing can return anything 

3232 elif arr.dtype.type is np.object_: 

3233 if arr.dtype is not elem.dtype: 

3234 # elem is an array, but dtypes do not match, so must be 

3235 # an element 

3236 return True 

3237 

3238 # well-behaved subclass that only returns 0d arrays when 

3239 # expected - this is not a scalar 

3240 elif type(arr).__getitem__ == ndarray.__getitem__: 

3241 return False 

3242 

3243 return None 

3244 

3245 if _mask is not nomask: 

3246 # _mask cannot be a subclass, so it tells us whether we should 

3247 # expect a scalar. It also cannot be of dtype object. 

3248 mout = _mask[indx] 

3249 scalar_expected = _is_scalar(mout) 

3250 

3251 else: 

3252 # attempt to apply the heuristic to avoid constructing a full mask 

3253 mout = nomask 

3254 scalar_expected = _scalar_heuristic(self.data, dout) 

3255 if scalar_expected is None: 

3256 # heuristics have failed 

3257 # construct a full array, so we can be certain. This is costly. 

3258 # we could also fall back on ndarray.__getitem__(self.data, indx) 

3259 scalar_expected = _is_scalar(getmaskarray(self)[indx]) 

3260 

3261 # Did we extract a single item? 

3262 if scalar_expected: 

3263 # A record 

3264 if isinstance(dout, np.void): 

3265 # We should always re-cast to mvoid, otherwise users can 

3266 # change masks on rows that already have masked values, but not 

3267 # on rows that have no masked values, which is inconsistent. 

3268 return mvoid(dout, mask=mout, hardmask=self._hardmask) 

3269 

3270 # special case introduced in gh-5962 

3271 elif (self.dtype.type is np.object_ and 

3272 isinstance(dout, np.ndarray) and 

3273 dout is not masked): 

3274 # If masked, turn into a MaskedArray, with everything masked. 

3275 if mout: 

3276 return MaskedArray(dout, mask=True) 

3277 else: 

3278 return dout 

3279 

3280 # Just a scalar 

3281 else: 

3282 if mout: 

3283 return masked 

3284 else: 

3285 return dout 

3286 else: 

3287 # Force dout to MA 

3288 dout = dout.view(type(self)) 

3289 # Inherit attributes from self 

3290 dout._update_from(self) 

3291 # Check the fill_value 

3292 if is_string_or_list_of_strings(indx): 

3293 if self._fill_value is not None: 

3294 dout._fill_value = self._fill_value[indx] 

3295 

3296 # Something like gh-15895 has happened if this check fails. 

3297 # _fill_value should always be an ndarray. 

3298 if not isinstance(dout._fill_value, np.ndarray): 

3299 raise RuntimeError('Internal NumPy error.') 

3300 # If we're indexing a multidimensional field in a 

3301 # structured array (such as dtype("(2,)i2,(2,)i1")), 

3302 # dimensionality goes up (M[field].ndim == M.ndim + 

3303 # M.dtype[field].ndim). That's fine for 

3304 # M[field] but problematic for M[field].fill_value 

3305 # which should have shape () to avoid breaking several 

3306 # methods. There is no great way out, so set to 

3307 # first element. See issue #6723. 

3308 if dout._fill_value.ndim > 0: 

3309 if not (dout._fill_value == 

3310 dout._fill_value.flat[0]).all(): 

3311 warnings.warn( 

3312 "Upon accessing multidimensional field " 

3313 f"{indx!s}, need to keep dimensionality " 

3314 "of fill_value at 0. Discarding " 

3315 "heterogeneous fill_value and setting " 

3316 f"all to {dout._fill_value[0]!s}.", 

3317 stacklevel=2) 

3318 # Need to use `.flat[0:1].squeeze(...)` instead of just 

3319 # `.flat[0]` to ensure the result is a 0d array and not 

3320 # a scalar. 

3321 dout._fill_value = dout._fill_value.flat[0:1].squeeze(axis=0) 

3322 dout._isfield = True 

3323 # Update the mask if needed 

3324 if mout is not nomask: 

3325 # set shape to match that of data; this is needed for matrices 

3326 dout._mask = reshape(mout, dout.shape) 

3327 dout._sharedmask = True 

3328 # Note: Don't try to check for m.any(), that'll take too long 

3329 return dout 

3330 

3331 # setitem may put NaNs into integer arrays or occasionally overflow a 

3332 # float. But this may happen in masked values, so avoid otherwise 

3333 # correct warnings (as is typical also in masked calculations). 

3334 @np.errstate(over='ignore', invalid='ignore') 

3335 def __setitem__(self, indx, value): 

3336 """ 

3337 x.__setitem__(i, y) <==> x[i]=y 

3338 

3339 Set item described by index. If value is masked, masks those 

3340 locations. 

3341 

3342 """ 

3343 if self is masked: 

3344 raise MaskError('Cannot alter the masked element.') 

3345 _data = self._data 

3346 _mask = self._mask 

3347 if isinstance(indx, str): 

3348 _data[indx] = value 

3349 if _mask is nomask: 

3350 self._mask = _mask = make_mask_none(self.shape, self.dtype) 

3351 _mask[indx] = getmask(value) 

3352 return 

3353 

3354 _dtype = _data.dtype 

3355 

3356 if value is masked: 

3357 # The mask wasn't set: create a full version. 

3358 if _mask is nomask: 

3359 _mask = self._mask = make_mask_none(self.shape, _dtype) 

3360 # Now, set the mask to its value. 

3361 if _dtype.names is not None: 

3362 _mask[indx] = tuple([True] * len(_dtype.names)) 

3363 else: 

3364 _mask[indx] = True 

3365 return 

3366 

3367 # Get the _data part of the new value 

3368 dval = getattr(value, '_data', value) 

3369 # Get the _mask part of the new value 

3370 mval = getmask(value) 

3371 if _dtype.names is not None and mval is nomask: 

3372 mval = tuple([False] * len(_dtype.names)) 

3373 if _mask is nomask: 

3374 # Set the data, then the mask 

3375 _data[indx] = dval 

3376 if mval is not nomask: 

3377 _mask = self._mask = make_mask_none(self.shape, _dtype) 

3378 _mask[indx] = mval 

3379 elif not self._hardmask: 

3380 # Set the data, then the mask 

3381 if (isinstance(indx, masked_array) and 

3382 not isinstance(value, masked_array)): 

3383 _data[indx.data] = dval 

3384 else: 

3385 _data[indx] = dval 

3386 _mask[indx] = mval 

3387 elif hasattr(indx, 'dtype') and (indx.dtype == MaskType): 

3388 indx = indx * umath.logical_not(_mask) 

3389 _data[indx] = dval 

3390 else: 

3391 if _dtype.names is not None: 

3392 err_msg = "Flexible 'hard' masks are not yet supported." 

3393 raise NotImplementedError(err_msg) 

3394 mindx = mask_or(_mask[indx], mval, copy=True) 

3395 dindx = self._data[indx] 

3396 if dindx.size > 1: 

3397 np.copyto(dindx, dval, where=~mindx) 

3398 elif mindx is nomask: 

3399 dindx = dval 

3400 _data[indx] = dindx 

3401 _mask[indx] = mindx 

3402 return 

3403 

3404 # Define so that we can overwrite the setter. 

3405 @property 

3406 def dtype(self): 

3407 return super().dtype 

3408 

3409 @dtype.setter 

3410 def dtype(self, dtype): 

3411 super(MaskedArray, type(self)).dtype.__set__(self, dtype) 

3412 if self._mask is not nomask: 

3413 self._mask = self._mask.view(make_mask_descr(dtype), ndarray) 

3414 # Try to reset the shape of the mask (if we don't have a void). 

3415 # This raises a ValueError if the dtype change won't work. 

3416 try: 

3417 self._mask.shape = self.shape 

3418 except (AttributeError, TypeError): 

3419 pass 

3420 

3421 @property 

3422 def shape(self): 

3423 return super().shape 

3424 

3425 @shape.setter 

3426 def shape(self, shape): 

3427 super(MaskedArray, type(self)).shape.__set__(self, shape) 

3428 # Cannot use self._mask, since it may not (yet) exist when a 

3429 # masked matrix sets the shape. 

3430 if getmask(self) is not nomask: 

3431 self._mask.shape = self.shape 

3432 

3433 def __setmask__(self, mask, copy=False): 

3434 """ 

3435 Set the mask. 

3436 

3437 """ 

3438 idtype = self.dtype 

3439 current_mask = self._mask 

3440 if mask is masked: 

3441 mask = True 

3442 

3443 if current_mask is nomask: 

3444 # Make sure the mask is set 

3445 # Just don't do anything if there's nothing to do. 

3446 if mask is nomask: 

3447 return 

3448 current_mask = self._mask = make_mask_none(self.shape, idtype) 

3449 

3450 if idtype.names is None: 

3451 # No named fields. 

3452 # Hardmask: don't unmask the data 

3453 if self._hardmask: 

3454 current_mask |= mask 

3455 # Softmask: set everything to False 

3456 # If it's obviously a compatible scalar, use a quick update 

3457 # method. 

3458 elif isinstance(mask, (int, float, np.bool_, np.number)): 

3459 current_mask[...] = mask 

3460 # Otherwise fall back to the slower, general purpose way. 

3461 else: 

3462 current_mask.flat = mask 

3463 else: 

3464 # Named fields w/ 

3465 mdtype = current_mask.dtype 

3466 mask = np.array(mask, copy=False) 

3467 # Mask is a singleton 

3468 if not mask.ndim: 

3469 # It's a boolean : make a record 

3470 if mask.dtype.kind == 'b': 

3471 mask = np.array(tuple([mask.item()] * len(mdtype)), 

3472 dtype=mdtype) 

3473 # It's a record: make sure the dtype is correct 

3474 else: 

3475 mask = mask.astype(mdtype) 

3476 # Mask is a sequence 

3477 else: 

3478 # Make sure the new mask is a ndarray with the proper dtype 

3479 try: 

3480 mask = np.array(mask, copy=copy, dtype=mdtype) 

3481 # Or assume it's a sequence of bool/int 

3482 except TypeError: 

3483 mask = np.array([tuple([m] * len(mdtype)) for m in mask], 

3484 dtype=mdtype) 

3485 # Hardmask: don't unmask the data 

3486 if self._hardmask: 

3487 for n in idtype.names: 

3488 current_mask[n] |= mask[n] 

3489 # Softmask: set everything to False 

3490 # If it's obviously a compatible scalar, use a quick update 

3491 # method. 

3492 elif isinstance(mask, (int, float, np.bool_, np.number)): 

3493 current_mask[...] = mask 

3494 # Otherwise fall back to the slower, general purpose way. 

3495 else: 

3496 current_mask.flat = mask 

3497 # Reshape if needed 

3498 if current_mask.shape: 

3499 current_mask.shape = self.shape 

3500 return 

3501 

3502 _set_mask = __setmask__ 

3503 

3504 @property 

3505 def mask(self): 

3506 """ Current mask. """ 

3507 

3508 # We could try to force a reshape, but that wouldn't work in some 

3509 # cases. 

3510 # Return a view so that the dtype and shape cannot be changed in place 

3511 # This still preserves nomask by identity 

3512 return self._mask.view() 

3513 

3514 @mask.setter 

3515 def mask(self, value): 

3516 self.__setmask__(value) 

3517 

3518 @property 

3519 def recordmask(self): 

3520 """ 

3521 Get or set the mask of the array if it has no named fields. For 

3522 structured arrays, returns a ndarray of booleans where entries are 

3523 ``True`` if **all** the fields are masked, ``False`` otherwise: 

3524 

3525 >>> x = np.ma.array([(1, 1), (2, 2), (3, 3), (4, 4), (5, 5)], 

3526 ... mask=[(0, 0), (1, 0), (1, 1), (0, 1), (0, 0)], 

3527 ... dtype=[('a', int), ('b', int)]) 

3528 >>> x.recordmask 

3529 array([False, False, True, False, False]) 

3530 """ 

3531 

3532 _mask = self._mask.view(ndarray) 

3533 if _mask.dtype.names is None: 

3534 return _mask 

3535 return np.all(flatten_structured_array(_mask), axis=-1) 

3536 

3537 @recordmask.setter 

3538 def recordmask(self, mask): 

3539 raise NotImplementedError("Coming soon: setting the mask per records!") 

3540 

3541 def harden_mask(self): 

3542 """ 

3543 Force the mask to hard, preventing unmasking by assignment. 

3544 

3545 Whether the mask of a masked array is hard or soft is determined by 

3546 its `~ma.MaskedArray.hardmask` property. `harden_mask` sets 

3547 `~ma.MaskedArray.hardmask` to ``True`` (and returns the modified 

3548 self). 

3549 

3550 See Also 

3551 -------- 

3552 ma.MaskedArray.hardmask 

3553 ma.MaskedArray.soften_mask 

3554 

3555 """ 

3556 self._hardmask = True 

3557 return self 

3558 

3559 def soften_mask(self): 

3560 """ 

3561 Force the mask to soft (default), allowing unmasking by assignment. 

3562 

3563 Whether the mask of a masked array is hard or soft is determined by 

3564 its `~ma.MaskedArray.hardmask` property. `soften_mask` sets 

3565 `~ma.MaskedArray.hardmask` to ``False`` (and returns the modified 

3566 self). 

3567 

3568 See Also 

3569 -------- 

3570 ma.MaskedArray.hardmask 

3571 ma.MaskedArray.harden_mask 

3572 

3573 """ 

3574 self._hardmask = False 

3575 return self 

3576 

3577 @property 

3578 def hardmask(self): 

3579 """ 

3580 Specifies whether values can be unmasked through assignments. 

3581 

3582 By default, assigning definite values to masked array entries will 

3583 unmask them. When `hardmask` is ``True``, the mask will not change 

3584 through assignments. 

3585 

3586 See Also 

3587 -------- 

3588 ma.MaskedArray.harden_mask 

3589 ma.MaskedArray.soften_mask 

3590 

3591 Examples 

3592 -------- 

3593 >>> x = np.arange(10) 

3594 >>> m = np.ma.masked_array(x, x>5) 

3595 >>> assert not m.hardmask 

3596 

3597 Since `m` has a soft mask, assigning an element value unmasks that 

3598 element: 

3599 

3600 >>> m[8] = 42 

3601 >>> m 

3602 masked_array(data=[0, 1, 2, 3, 4, 5, --, --, 42, --], 

3603 mask=[False, False, False, False, False, False, 

3604 True, True, False, True], 

3605 fill_value=999999) 

3606 

3607 After hardening, the mask is not affected by assignments: 

3608 

3609 >>> hardened = np.ma.harden_mask(m) 

3610 >>> assert m.hardmask and hardened is m 

3611 >>> m[:] = 23 

3612 >>> m 

3613 masked_array(data=[23, 23, 23, 23, 23, 23, --, --, 23, --], 

3614 mask=[False, False, False, False, False, False, 

3615 True, True, False, True], 

3616 fill_value=999999) 

3617 

3618 """ 

3619 return self._hardmask 

3620 

3621 def unshare_mask(self): 

3622 """ 

3623 Copy the mask and set the `sharedmask` flag to ``False``. 

3624 

3625 Whether the mask is shared between masked arrays can be seen from 

3626 the `sharedmask` property. `unshare_mask` ensures the mask is not 

3627 shared. A copy of the mask is only made if it was shared. 

3628 

3629 See Also 

3630 -------- 

3631 sharedmask 

3632 

3633 """ 

3634 if self._sharedmask: 

3635 self._mask = self._mask.copy() 

3636 self._sharedmask = False 

3637 return self 

3638 

3639 @property 

3640 def sharedmask(self): 

3641 """ Share status of the mask (read-only). """ 

3642 return self._sharedmask 

3643 

3644 def shrink_mask(self): 

3645 """ 

3646 Reduce a mask to nomask when possible. 

3647 

3648 Parameters 

3649 ---------- 

3650 None 

3651 

3652 Returns 

3653 ------- 

3654 None 

3655 

3656 Examples 

3657 -------- 

3658 >>> x = np.ma.array([[1,2 ], [3, 4]], mask=[0]*4) 

3659 >>> x.mask 

3660 array([[False, False], 

3661 [False, False]]) 

3662 >>> x.shrink_mask() 

3663 masked_array( 

3664 data=[[1, 2], 

3665 [3, 4]], 

3666 mask=False, 

3667 fill_value=999999) 

3668 >>> x.mask 

3669 False 

3670 

3671 """ 

3672 self._mask = _shrink_mask(self._mask) 

3673 return self 

3674 

3675 @property 

3676 def baseclass(self): 

3677 """ Class of the underlying data (read-only). """ 

3678 return self._baseclass 

3679 

3680 def _get_data(self): 

3681 """ 

3682 Returns the underlying data, as a view of the masked array. 

3683 

3684 If the underlying data is a subclass of :class:`numpy.ndarray`, it is 

3685 returned as such. 

3686 

3687 >>> x = np.ma.array(np.matrix([[1, 2], [3, 4]]), mask=[[0, 1], [1, 0]]) 

3688 >>> x.data 

3689 matrix([[1, 2], 

3690 [3, 4]]) 

3691 

3692 The type of the data can be accessed through the :attr:`baseclass` 

3693 attribute. 

3694 """ 

3695 return ndarray.view(self, self._baseclass) 

3696 

3697 _data = property(fget=_get_data) 

3698 data = property(fget=_get_data) 

3699 

3700 @property 

3701 def flat(self): 

3702 """ Return a flat iterator, or set a flattened version of self to value. """ 

3703 return MaskedIterator(self) 

3704 

3705 @flat.setter 

3706 def flat(self, value): 

3707 y = self.ravel() 

3708 y[:] = value 

3709 

3710 @property 

3711 def fill_value(self): 

3712 """ 

3713 The filling value of the masked array is a scalar. When setting, None 

3714 will set to a default based on the data type. 

3715 

3716 Examples 

3717 -------- 

3718 >>> for dt in [np.int32, np.int64, np.float64, np.complex128]: 

3719 ... np.ma.array([0, 1], dtype=dt).get_fill_value() 

3720 ... 

3721 999999 

3722 999999 

3723 1e+20 

3724 (1e+20+0j) 

3725 

3726 >>> x = np.ma.array([0, 1.], fill_value=-np.inf) 

3727 >>> x.fill_value 

3728 -inf 

3729 >>> x.fill_value = np.pi 

3730 >>> x.fill_value 

3731 3.1415926535897931 # may vary 

3732 

3733 Reset to default: 

3734 

3735 >>> x.fill_value = None 

3736 >>> x.fill_value 

3737 1e+20 

3738 

3739 """ 

3740 if self._fill_value is None: 

3741 self._fill_value = _check_fill_value(None, self.dtype) 

3742 

3743 # Temporary workaround to account for the fact that str and bytes 

3744 # scalars cannot be indexed with (), whereas all other numpy 

3745 # scalars can. See issues #7259 and #7267. 

3746 # The if-block can be removed after #7267 has been fixed. 

3747 if isinstance(self._fill_value, ndarray): 

3748 return self._fill_value[()] 

3749 return self._fill_value 

3750 

3751 @fill_value.setter 

3752 def fill_value(self, value=None): 

3753 target = _check_fill_value(value, self.dtype) 

3754 if not target.ndim == 0: 

3755 # 2019-11-12, 1.18.0 

3756 warnings.warn( 

3757 "Non-scalar arrays for the fill value are deprecated. Use " 

3758 "arrays with scalar values instead. The filled function " 

3759 "still supports any array as `fill_value`.", 

3760 DeprecationWarning, stacklevel=2) 

3761 

3762 _fill_value = self._fill_value 

3763 if _fill_value is None: 

3764 # Create the attribute if it was undefined 

3765 self._fill_value = target 

3766 else: 

3767 # Don't overwrite the attribute, just fill it (for propagation) 

3768 _fill_value[()] = target 

3769 

3770 # kept for compatibility 

3771 get_fill_value = fill_value.fget 

3772 set_fill_value = fill_value.fset 

3773 

3774 def filled(self, fill_value=None): 

3775 """ 

3776 Return a copy of self, with masked values filled with a given value. 

3777 **However**, if there are no masked values to fill, self will be 

3778 returned instead as an ndarray. 

3779 

3780 Parameters 

3781 ---------- 

3782 fill_value : array_like, optional 

3783 The value to use for invalid entries. Can be scalar or non-scalar. 

3784 If non-scalar, the resulting ndarray must be broadcastable over 

3785 input array. Default is None, in which case, the `fill_value` 

3786 attribute of the array is used instead. 

3787 

3788 Returns 

3789 ------- 

3790 filled_array : ndarray 

3791 A copy of ``self`` with invalid entries replaced by *fill_value* 

3792 (be it the function argument or the attribute of ``self``), or 

3793 ``self`` itself as an ndarray if there are no invalid entries to 

3794 be replaced. 

3795 

3796 Notes 

3797 ----- 

3798 The result is **not** a MaskedArray! 

3799 

3800 Examples 

3801 -------- 

3802 >>> x = np.ma.array([1,2,3,4,5], mask=[0,0,1,0,1], fill_value=-999) 

3803 >>> x.filled() 

3804 array([ 1, 2, -999, 4, -999]) 

3805 >>> x.filled(fill_value=1000) 

3806 array([ 1, 2, 1000, 4, 1000]) 

3807 >>> type(x.filled()) 

3808 <class 'numpy.ndarray'> 

3809 

3810 Subclassing is preserved. This means that if, e.g., the data part of 

3811 the masked array is a recarray, `filled` returns a recarray: 

3812 

3813 >>> x = np.array([(-1, 2), (-3, 4)], dtype='i8,i8').view(np.recarray) 

3814 >>> m = np.ma.array(x, mask=[(True, False), (False, True)]) 

3815 >>> m.filled() 

3816 rec.array([(999999, 2), ( -3, 999999)], 

3817 dtype=[('f0', '<i8'), ('f1', '<i8')]) 

3818 """ 

3819 m = self._mask 

3820 if m is nomask: 

3821 return self._data 

3822 

3823 if fill_value is None: 

3824 fill_value = self.fill_value 

3825 else: 

3826 fill_value = _check_fill_value(fill_value, self.dtype) 

3827 

3828 if self is masked_singleton: 

3829 return np.asanyarray(fill_value) 

3830 

3831 if m.dtype.names is not None: 

3832 result = self._data.copy('K') 

3833 _recursive_filled(result, self._mask, fill_value) 

3834 elif not m.any(): 

3835 return self._data 

3836 else: 

3837 result = self._data.copy('K') 

3838 try: 

3839 np.copyto(result, fill_value, where=m) 

3840 except (TypeError, AttributeError): 

3841 fill_value = narray(fill_value, dtype=object) 

3842 d = result.astype(object) 

3843 result = np.choose(m, (d, fill_value)) 

3844 except IndexError: 

3845 # ok, if scalar 

3846 if self._data.shape: 

3847 raise 

3848 elif m: 

3849 result = np.array(fill_value, dtype=self.dtype) 

3850 else: 

3851 result = self._data 

3852 return result 

3853 

3854 def compressed(self): 

3855 """ 

3856 Return all the non-masked data as a 1-D array. 

3857 

3858 Returns 

3859 ------- 

3860 data : ndarray 

3861 A new `ndarray` holding the non-masked data is returned. 

3862 

3863 Notes 

3864 ----- 

3865 The result is **not** a MaskedArray! 

3866 

3867 Examples 

3868 -------- 

3869 >>> x = np.ma.array(np.arange(5), mask=[0]*2 + [1]*3) 

3870 >>> x.compressed() 

3871 array([0, 1]) 

3872 >>> type(x.compressed()) 

3873 <class 'numpy.ndarray'> 

3874 

3875 """ 

3876 data = ndarray.ravel(self._data) 

3877 if self._mask is not nomask: 

3878 data = data.compress(np.logical_not(ndarray.ravel(self._mask))) 

3879 return data 

3880 

3881 def compress(self, condition, axis=None, out=None): 

3882 """ 

3883 Return `a` where condition is ``True``. 

3884 

3885 If condition is a `~ma.MaskedArray`, missing values are considered 

3886 as ``False``. 

3887 

3888 Parameters 

3889 ---------- 

3890 condition : var 

3891 Boolean 1-d array selecting which entries to return. If len(condition) 

3892 is less than the size of a along the axis, then output is truncated 

3893 to length of condition array. 

3894 axis : {None, int}, optional 

3895 Axis along which the operation must be performed. 

3896 out : {None, ndarray}, optional 

3897 Alternative output array in which to place the result. It must have 

3898 the same shape as the expected output but the type will be cast if 

3899 necessary. 

3900 

3901 Returns 

3902 ------- 

3903 result : MaskedArray 

3904 A :class:`~ma.MaskedArray` object. 

3905 

3906 Notes 

3907 ----- 

3908 Please note the difference with :meth:`compressed` ! 

3909 The output of :meth:`compress` has a mask, the output of 

3910 :meth:`compressed` does not. 

3911 

3912 Examples 

3913 -------- 

3914 >>> x = np.ma.array([[1,2,3],[4,5,6],[7,8,9]], mask=[0] + [1,0]*4) 

3915 >>> x 

3916 masked_array( 

3917 data=[[1, --, 3], 

3918 [--, 5, --], 

3919 [7, --, 9]], 

3920 mask=[[False, True, False], 

3921 [ True, False, True], 

3922 [False, True, False]], 

3923 fill_value=999999) 

3924 >>> x.compress([1, 0, 1]) 

3925 masked_array(data=[1, 3], 

3926 mask=[False, False], 

3927 fill_value=999999) 

3928 

3929 >>> x.compress([1, 0, 1], axis=1) 

3930 masked_array( 

3931 data=[[1, 3], 

3932 [--, --], 

3933 [7, 9]], 

3934 mask=[[False, False], 

3935 [ True, True], 

3936 [False, False]], 

3937 fill_value=999999) 

3938 

3939 """ 

3940 # Get the basic components 

3941 (_data, _mask) = (self._data, self._mask) 

3942 

3943 # Force the condition to a regular ndarray and forget the missing 

3944 # values. 

3945 condition = np.asarray(condition) 

3946 

3947 _new = _data.compress(condition, axis=axis, out=out).view(type(self)) 

3948 _new._update_from(self) 

3949 if _mask is not nomask: 

3950 _new._mask = _mask.compress(condition, axis=axis) 

3951 return _new 

3952 

3953 def _insert_masked_print(self): 

3954 """ 

3955 Replace masked values with masked_print_option, casting all innermost 

3956 dtypes to object. 

3957 """ 

3958 if masked_print_option.enabled(): 

3959 mask = self._mask 

3960 if mask is nomask: 

3961 res = self._data 

3962 else: 

3963 # convert to object array to make filled work 

3964 data = self._data 

3965 # For big arrays, to avoid a costly conversion to the 

3966 # object dtype, extract the corners before the conversion. 

3967 print_width = (self._print_width if self.ndim > 1 

3968 else self._print_width_1d) 

3969 for axis in range(self.ndim): 

3970 if data.shape[axis] > print_width: 

3971 ind = print_width // 2 

3972 arr = np.split(data, (ind, -ind), axis=axis) 

3973 data = np.concatenate((arr[0], arr[2]), axis=axis) 

3974 arr = np.split(mask, (ind, -ind), axis=axis) 

3975 mask = np.concatenate((arr[0], arr[2]), axis=axis) 

3976 

3977 rdtype = _replace_dtype_fields(self.dtype, "O") 

3978 res = data.astype(rdtype) 

3979 _recursive_printoption(res, mask, masked_print_option) 

3980 else: 

3981 res = self.filled(self.fill_value) 

3982 return res 

3983 

3984 def __str__(self): 

3985 return str(self._insert_masked_print()) 

3986 

3987 def __repr__(self): 

3988 """ 

3989 Literal string representation. 

3990 

3991 """ 

3992 if self._baseclass is np.ndarray: 

3993 name = 'array' 

3994 else: 

3995 name = self._baseclass.__name__ 

3996 

3997 

3998 # 2016-11-19: Demoted to legacy format 

3999 if np.core.arrayprint._get_legacy_print_mode() <= 113: 

4000 is_long = self.ndim > 1 

4001 parameters = dict( 

4002 name=name, 

4003 nlen=" " * len(name), 

4004 data=str(self), 

4005 mask=str(self._mask), 

4006 fill=str(self.fill_value), 

4007 dtype=str(self.dtype) 

4008 ) 

4009 is_structured = bool(self.dtype.names) 

4010 key = '{}_{}'.format( 

4011 'long' if is_long else 'short', 

4012 'flx' if is_structured else 'std' 

4013 ) 

4014 return _legacy_print_templates[key] % parameters 

4015 

4016 prefix = f"masked_{name}(" 

4017 

4018 dtype_needed = ( 

4019 not np.core.arrayprint.dtype_is_implied(self.dtype) or 

4020 np.all(self.mask) or 

4021 self.size == 0 

4022 ) 

4023 

4024 # determine which keyword args need to be shown 

4025 keys = ['data', 'mask', 'fill_value'] 

4026 if dtype_needed: 

4027 keys.append('dtype') 

4028 

4029 # array has only one row (non-column) 

4030 is_one_row = builtins.all(dim == 1 for dim in self.shape[:-1]) 

4031 

4032 # choose what to indent each keyword with 

4033 min_indent = 2 

4034 if is_one_row: 

4035 # first key on the same line as the type, remaining keys 

4036 # aligned by equals 

4037 indents = {} 

4038 indents[keys[0]] = prefix 

4039 for k in keys[1:]: 

4040 n = builtins.max(min_indent, len(prefix + keys[0]) - len(k)) 

4041 indents[k] = ' ' * n 

4042 prefix = '' # absorbed into the first indent 

4043 else: 

4044 # each key on its own line, indented by two spaces 

4045 indents = {k: ' ' * min_indent for k in keys} 

4046 prefix = prefix + '\n' # first key on the next line 

4047 

4048 # format the field values 

4049 reprs = {} 

4050 reprs['data'] = np.array2string( 

4051 self._insert_masked_print(), 

4052 separator=", ", 

4053 prefix=indents['data'] + 'data=', 

4054 suffix=',') 

4055 reprs['mask'] = np.array2string( 

4056 self._mask, 

4057 separator=", ", 

4058 prefix=indents['mask'] + 'mask=', 

4059 suffix=',') 

4060 reprs['fill_value'] = repr(self.fill_value) 

4061 if dtype_needed: 

4062 reprs['dtype'] = np.core.arrayprint.dtype_short_repr(self.dtype) 

4063 

4064 # join keys with values and indentations 

4065 result = ',\n'.join( 

4066 '{}{}={}'.format(indents[k], k, reprs[k]) 

4067 for k in keys 

4068 ) 

4069 return prefix + result + ')' 

4070 

4071 def _delegate_binop(self, other): 

4072 # This emulates the logic in 

4073 # private/binop_override.h:forward_binop_should_defer 

4074 if isinstance(other, type(self)): 

4075 return False 

4076 array_ufunc = getattr(other, "__array_ufunc__", False) 

4077 if array_ufunc is False: 

4078 other_priority = getattr(other, "__array_priority__", -1000000) 

4079 return self.__array_priority__ < other_priority 

4080 else: 

4081 # If array_ufunc is not None, it will be called inside the ufunc; 

4082 # None explicitly tells us to not call the ufunc, i.e., defer. 

4083 return array_ufunc is None 

4084 

4085 def _comparison(self, other, compare): 

4086 """Compare self with other using operator.eq or operator.ne. 

4087 

4088 When either of the elements is masked, the result is masked as well, 

4089 but the underlying boolean data are still set, with self and other 

4090 considered equal if both are masked, and unequal otherwise. 

4091 

4092 For structured arrays, all fields are combined, with masked values 

4093 ignored. The result is masked if all fields were masked, with self 

4094 and other considered equal only if both were fully masked. 

4095 """ 

4096 omask = getmask(other) 

4097 smask = self.mask 

4098 mask = mask_or(smask, omask, copy=True) 

4099 

4100 odata = getdata(other) 

4101 if mask.dtype.names is not None: 

4102 # only == and != are reasonably defined for structured dtypes, 

4103 # so give up early for all other comparisons: 

4104 if compare not in (operator.eq, operator.ne): 

4105 return NotImplemented 

4106 # For possibly masked structured arrays we need to be careful, 

4107 # since the standard structured array comparison will use all 

4108 # fields, masked or not. To avoid masked fields influencing the 

4109 # outcome, we set all masked fields in self to other, so they'll 

4110 # count as equal. To prepare, we ensure we have the right shape. 

4111 broadcast_shape = np.broadcast(self, odata).shape 

4112 sbroadcast = np.broadcast_to(self, broadcast_shape, subok=True) 

4113 sbroadcast._mask = mask 

4114 sdata = sbroadcast.filled(odata) 

4115 # Now take care of the mask; the merged mask should have an item 

4116 # masked if all fields were masked (in one and/or other). 

4117 mask = (mask == np.ones((), mask.dtype)) 

4118 

4119 else: 

4120 # For regular arrays, just use the data as they come. 

4121 sdata = self.data 

4122 

4123 check = compare(sdata, odata) 

4124 

4125 if isinstance(check, (np.bool_, bool)): 

4126 return masked if mask else check 

4127 

4128 if mask is not nomask and compare in (operator.eq, operator.ne): 

4129 # Adjust elements that were masked, which should be treated 

4130 # as equal if masked in both, unequal if masked in one. 

4131 # Note that this works automatically for structured arrays too. 

4132 # Ignore this for operations other than `==` and `!=` 

4133 check = np.where(mask, compare(smask, omask), check) 

4134 if mask.shape != check.shape: 

4135 # Guarantee consistency of the shape, making a copy since the 

4136 # the mask may need to get written to later. 

4137 mask = np.broadcast_to(mask, check.shape).copy() 

4138 

4139 check = check.view(type(self)) 

4140 check._update_from(self) 

4141 check._mask = mask 

4142 

4143 # Cast fill value to bool_ if needed. If it cannot be cast, the 

4144 # default boolean fill value is used. 

4145 if check._fill_value is not None: 

4146 try: 

4147 fill = _check_fill_value(check._fill_value, np.bool_) 

4148 except (TypeError, ValueError): 

4149 fill = _check_fill_value(None, np.bool_) 

4150 check._fill_value = fill 

4151 

4152 return check 

4153 

4154 def __eq__(self, other): 

4155 """Check whether other equals self elementwise. 

4156 

4157 When either of the elements is masked, the result is masked as well, 

4158 but the underlying boolean data are still set, with self and other 

4159 considered equal if both are masked, and unequal otherwise. 

4160 

4161 For structured arrays, all fields are combined, with masked values 

4162 ignored. The result is masked if all fields were masked, with self 

4163 and other considered equal only if both were fully masked. 

4164 """ 

4165 return self._comparison(other, operator.eq) 

4166 

4167 def __ne__(self, other): 

4168 """Check whether other does not equal self elementwise. 

4169 

4170 When either of the elements is masked, the result is masked as well, 

4171 but the underlying boolean data are still set, with self and other 

4172 considered equal if both are masked, and unequal otherwise. 

4173 

4174 For structured arrays, all fields are combined, with masked values 

4175 ignored. The result is masked if all fields were masked, with self 

4176 and other considered equal only if both were fully masked. 

4177 """ 

4178 return self._comparison(other, operator.ne) 

4179 

4180 # All other comparisons: 

4181 def __le__(self, other): 

4182 return self._comparison(other, operator.le) 

4183 

4184 def __lt__(self, other): 

4185 return self._comparison(other, operator.lt) 

4186 

4187 def __ge__(self, other): 

4188 return self._comparison(other, operator.ge) 

4189 

4190 def __gt__(self, other): 

4191 return self._comparison(other, operator.gt) 

4192 

4193 def __add__(self, other): 

4194 """ 

4195 Add self to other, and return a new masked array. 

4196 

4197 """ 

4198 if self._delegate_binop(other): 

4199 return NotImplemented 

4200 return add(self, other) 

4201 

4202 def __radd__(self, other): 

4203 """ 

4204 Add other to self, and return a new masked array. 

4205 

4206 """ 

4207 # In analogy with __rsub__ and __rdiv__, use original order: 

4208 # we get here from `other + self`. 

4209 return add(other, self) 

4210 

4211 def __sub__(self, other): 

4212 """ 

4213 Subtract other from self, and return a new masked array. 

4214 

4215 """ 

4216 if self._delegate_binop(other): 

4217 return NotImplemented 

4218 return subtract(self, other) 

4219 

4220 def __rsub__(self, other): 

4221 """ 

4222 Subtract self from other, and return a new masked array. 

4223 

4224 """ 

4225 return subtract(other, self) 

4226 

4227 def __mul__(self, other): 

4228 "Multiply self by other, and return a new masked array." 

4229 if self._delegate_binop(other): 

4230 return NotImplemented 

4231 return multiply(self, other) 

4232 

4233 def __rmul__(self, other): 

4234 """ 

4235 Multiply other by self, and return a new masked array. 

4236 

4237 """ 

4238 # In analogy with __rsub__ and __rdiv__, use original order: 

4239 # we get here from `other * self`. 

4240 return multiply(other, self) 

4241 

4242 def __div__(self, other): 

4243 """ 

4244 Divide other into self, and return a new masked array. 

4245 

4246 """ 

4247 if self._delegate_binop(other): 

4248 return NotImplemented 

4249 return divide(self, other) 

4250 

4251 def __truediv__(self, other): 

4252 """ 

4253 Divide other into self, and return a new masked array. 

4254 

4255 """ 

4256 if self._delegate_binop(other): 

4257 return NotImplemented 

4258 return true_divide(self, other) 

4259 

4260 def __rtruediv__(self, other): 

4261 """ 

4262 Divide self into other, and return a new masked array. 

4263 

4264 """ 

4265 return true_divide(other, self) 

4266 

4267 def __floordiv__(self, other): 

4268 """ 

4269 Divide other into self, and return a new masked array. 

4270 

4271 """ 

4272 if self._delegate_binop(other): 

4273 return NotImplemented 

4274 return floor_divide(self, other) 

4275 

4276 def __rfloordiv__(self, other): 

4277 """ 

4278 Divide self into other, and return a new masked array. 

4279 

4280 """ 

4281 return floor_divide(other, self) 

4282 

4283 def __pow__(self, other): 

4284 """ 

4285 Raise self to the power other, masking the potential NaNs/Infs 

4286 

4287 """ 

4288 if self._delegate_binop(other): 

4289 return NotImplemented 

4290 return power(self, other) 

4291 

4292 def __rpow__(self, other): 

4293 """ 

4294 Raise other to the power self, masking the potential NaNs/Infs 

4295 

4296 """ 

4297 return power(other, self) 

4298 

4299 def __iadd__(self, other): 

4300 """ 

4301 Add other to self in-place. 

4302 

4303 """ 

4304 m = getmask(other) 

4305 if self._mask is nomask: 

4306 if m is not nomask and m.any(): 

4307 self._mask = make_mask_none(self.shape, self.dtype) 

4308 self._mask += m 

4309 else: 

4310 if m is not nomask: 

4311 self._mask += m 

4312 other_data = getdata(other) 

4313 other_data = np.where(self._mask, other_data.dtype.type(0), other_data) 

4314 self._data.__iadd__(other_data) 

4315 return self 

4316 

4317 def __isub__(self, other): 

4318 """ 

4319 Subtract other from self in-place. 

4320 

4321 """ 

4322 m = getmask(other) 

4323 if self._mask is nomask: 

4324 if m is not nomask and m.any(): 

4325 self._mask = make_mask_none(self.shape, self.dtype) 

4326 self._mask += m 

4327 elif m is not nomask: 

4328 self._mask += m 

4329 other_data = getdata(other) 

4330 other_data = np.where(self._mask, other_data.dtype.type(0), other_data) 

4331 self._data.__isub__(other_data) 

4332 return self 

4333 

4334 def __imul__(self, other): 

4335 """ 

4336 Multiply self by other in-place. 

4337 

4338 """ 

4339 m = getmask(other) 

4340 if self._mask is nomask: 

4341 if m is not nomask and m.any(): 

4342 self._mask = make_mask_none(self.shape, self.dtype) 

4343 self._mask += m 

4344 elif m is not nomask: 

4345 self._mask += m 

4346 other_data = getdata(other) 

4347 other_data = np.where(self._mask, other_data.dtype.type(1), other_data) 

4348 self._data.__imul__(other_data) 

4349 return self 

4350 

4351 def __idiv__(self, other): 

4352 """ 

4353 Divide self by other in-place. 

4354 

4355 """ 

4356 other_data = getdata(other) 

4357 dom_mask = _DomainSafeDivide().__call__(self._data, other_data) 

4358 other_mask = getmask(other) 

4359 new_mask = mask_or(other_mask, dom_mask) 

4360 # The following 4 lines control the domain filling 

4361 if dom_mask.any(): 

4362 (_, fval) = ufunc_fills[np.divide] 

4363 other_data = np.where( 

4364 dom_mask, other_data.dtype.type(fval), other_data) 

4365 self._mask |= new_mask 

4366 other_data = np.where(self._mask, other_data.dtype.type(1), other_data) 

4367 self._data.__idiv__(other_data) 

4368 return self 

4369 

4370 def __ifloordiv__(self, other): 

4371 """ 

4372 Floor divide self by other in-place. 

4373 

4374 """ 

4375 other_data = getdata(other) 

4376 dom_mask = _DomainSafeDivide().__call__(self._data, other_data) 

4377 other_mask = getmask(other) 

4378 new_mask = mask_or(other_mask, dom_mask) 

4379 # The following 3 lines control the domain filling 

4380 if dom_mask.any(): 

4381 (_, fval) = ufunc_fills[np.floor_divide] 

4382 other_data = np.where( 

4383 dom_mask, other_data.dtype.type(fval), other_data) 

4384 self._mask |= new_mask 

4385 other_data = np.where(self._mask, other_data.dtype.type(1), other_data) 

4386 self._data.__ifloordiv__(other_data) 

4387 return self 

4388 

4389 def __itruediv__(self, other): 

4390 """ 

4391 True divide self by other in-place. 

4392 

4393 """ 

4394 other_data = getdata(other) 

4395 dom_mask = _DomainSafeDivide().__call__(self._data, other_data) 

4396 other_mask = getmask(other) 

4397 new_mask = mask_or(other_mask, dom_mask) 

4398 # The following 3 lines control the domain filling 

4399 if dom_mask.any(): 

4400 (_, fval) = ufunc_fills[np.true_divide] 

4401 other_data = np.where( 

4402 dom_mask, other_data.dtype.type(fval), other_data) 

4403 self._mask |= new_mask 

4404 other_data = np.where(self._mask, other_data.dtype.type(1), other_data) 

4405 self._data.__itruediv__(other_data) 

4406 return self 

4407 

4408 def __ipow__(self, other): 

4409 """ 

4410 Raise self to the power other, in place. 

4411 

4412 """ 

4413 other_data = getdata(other) 

4414 other_data = np.where(self._mask, other_data.dtype.type(1), other_data) 

4415 other_mask = getmask(other) 

4416 with np.errstate(divide='ignore', invalid='ignore'): 

4417 self._data.__ipow__(other_data) 

4418 invalid = np.logical_not(np.isfinite(self._data)) 

4419 if invalid.any(): 

4420 if self._mask is not nomask: 

4421 self._mask |= invalid 

4422 else: 

4423 self._mask = invalid 

4424 np.copyto(self._data, self.fill_value, where=invalid) 

4425 new_mask = mask_or(other_mask, invalid) 

4426 self._mask = mask_or(self._mask, new_mask) 

4427 return self 

4428 

4429 def __float__(self): 

4430 """ 

4431 Convert to float. 

4432 

4433 """ 

4434 if self.size > 1: 

4435 raise TypeError("Only length-1 arrays can be converted " 

4436 "to Python scalars") 

4437 elif self._mask: 

4438 warnings.warn("Warning: converting a masked element to nan.", stacklevel=2) 

4439 return np.nan 

4440 return float(self.item()) 

4441 

4442 def __int__(self): 

4443 """ 

4444 Convert to int. 

4445 

4446 """ 

4447 if self.size > 1: 

4448 raise TypeError("Only length-1 arrays can be converted " 

4449 "to Python scalars") 

4450 elif self._mask: 

4451 raise MaskError('Cannot convert masked element to a Python int.') 

4452 return int(self.item()) 

4453 

4454 @property 

4455 def imag(self): 

4456 """ 

4457 The imaginary part of the masked array. 

4458 

4459 This property is a view on the imaginary part of this `MaskedArray`. 

4460 

4461 See Also 

4462 -------- 

4463 real 

4464 

4465 Examples 

4466 -------- 

4467 >>> x = np.ma.array([1+1.j, -2j, 3.45+1.6j], mask=[False, True, False]) 

4468 >>> x.imag 

4469 masked_array(data=[1.0, --, 1.6], 

4470 mask=[False, True, False], 

4471 fill_value=1e+20) 

4472 

4473 """ 

4474 result = self._data.imag.view(type(self)) 

4475 result.__setmask__(self._mask) 

4476 return result 

4477 

4478 # kept for compatibility 

4479 get_imag = imag.fget 

4480 

4481 @property 

4482 def real(self): 

4483 """ 

4484 The real part of the masked array. 

4485 

4486 This property is a view on the real part of this `MaskedArray`. 

4487 

4488 See Also 

4489 -------- 

4490 imag 

4491 

4492 Examples 

4493 -------- 

4494 >>> x = np.ma.array([1+1.j, -2j, 3.45+1.6j], mask=[False, True, False]) 

4495 >>> x.real 

4496 masked_array(data=[1.0, --, 3.45], 

4497 mask=[False, True, False], 

4498 fill_value=1e+20) 

4499 

4500 """ 

4501 result = self._data.real.view(type(self)) 

4502 result.__setmask__(self._mask) 

4503 return result 

4504 

4505 # kept for compatibility 

4506 get_real = real.fget 

4507 

4508 def count(self, axis=None, keepdims=np._NoValue): 

4509 """ 

4510 Count the non-masked elements of the array along the given axis. 

4511 

4512 Parameters 

4513 ---------- 

4514 axis : None or int or tuple of ints, optional 

4515 Axis or axes along which the count is performed. 

4516 The default, None, performs the count over all 

4517 the dimensions of the input array. `axis` may be negative, in 

4518 which case it counts from the last to the first axis. 

4519 

4520 .. versionadded:: 1.10.0 

4521 

4522 If this is a tuple of ints, the count is performed on multiple 

4523 axes, instead of a single axis or all the axes as before. 

4524 keepdims : bool, optional 

4525 If this is set to True, the axes which are reduced are left 

4526 in the result as dimensions with size one. With this option, 

4527 the result will broadcast correctly against the array. 

4528 

4529 Returns 

4530 ------- 

4531 result : ndarray or scalar 

4532 An array with the same shape as the input array, with the specified 

4533 axis removed. If the array is a 0-d array, or if `axis` is None, a 

4534 scalar is returned. 

4535 

4536 See Also 

4537 -------- 

4538 ma.count_masked : Count masked elements in array or along a given axis. 

4539 

4540 Examples 

4541 -------- 

4542 >>> import numpy.ma as ma 

4543 >>> a = ma.arange(6).reshape((2, 3)) 

4544 >>> a[1, :] = ma.masked 

4545 >>> a 

4546 masked_array( 

4547 data=[[0, 1, 2], 

4548 [--, --, --]], 

4549 mask=[[False, False, False], 

4550 [ True, True, True]], 

4551 fill_value=999999) 

4552 >>> a.count() 

4553 3 

4554 

4555 When the `axis` keyword is specified an array of appropriate size is 

4556 returned. 

4557 

4558 >>> a.count(axis=0) 

4559 array([1, 1, 1]) 

4560 >>> a.count(axis=1) 

4561 array([3, 0]) 

4562 

4563 """ 

4564 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

4565 

4566 m = self._mask 

4567 # special case for matrices (we assume no other subclasses modify 

4568 # their dimensions) 

4569 if isinstance(self.data, np.matrix): 

4570 if m is nomask: 

4571 m = np.zeros(self.shape, dtype=np.bool_) 

4572 m = m.view(type(self.data)) 

4573 

4574 if m is nomask: 

4575 # compare to _count_reduce_items in _methods.py 

4576 

4577 if self.shape == (): 

4578 if axis not in (None, 0): 

4579 raise np.AxisError(axis=axis, ndim=self.ndim) 

4580 return 1 

4581 elif axis is None: 

4582 if kwargs.get('keepdims', False): 

4583 return np.array(self.size, dtype=np.intp, ndmin=self.ndim) 

4584 return self.size 

4585 

4586 axes = normalize_axis_tuple(axis, self.ndim) 

4587 items = 1 

4588 for ax in axes: 

4589 items *= self.shape[ax] 

4590 

4591 if kwargs.get('keepdims', False): 

4592 out_dims = list(self.shape) 

4593 for a in axes: 

4594 out_dims[a] = 1 

4595 else: 

4596 out_dims = [d for n, d in enumerate(self.shape) 

4597 if n not in axes] 

4598 # make sure to return a 0-d array if axis is supplied 

4599 return np.full(out_dims, items, dtype=np.intp) 

4600 

4601 # take care of the masked singleton 

4602 if self is masked: 

4603 return 0 

4604 

4605 return (~m).sum(axis=axis, dtype=np.intp, **kwargs) 

4606 

4607 def ravel(self, order='C'): 

4608 """ 

4609 Returns a 1D version of self, as a view. 

4610 

4611 Parameters 

4612 ---------- 

4613 order : {'C', 'F', 'A', 'K'}, optional 

4614 The elements of `a` are read using this index order. 'C' means to 

4615 index the elements in C-like order, with the last axis index 

4616 changing fastest, back to the first axis index changing slowest. 

4617 'F' means to index the elements in Fortran-like index order, with 

4618 the first index changing fastest, and the last index changing 

4619 slowest. Note that the 'C' and 'F' options take no account of the 

4620 memory layout of the underlying array, and only refer to the order 

4621 of axis indexing. 'A' means to read the elements in Fortran-like 

4622 index order if `m` is Fortran *contiguous* in memory, C-like order 

4623 otherwise. 'K' means to read the elements in the order they occur 

4624 in memory, except for reversing the data when strides are negative. 

4625 By default, 'C' index order is used. 

4626 (Masked arrays currently use 'A' on the data when 'K' is passed.) 

4627 

4628 Returns 

4629 ------- 

4630 MaskedArray 

4631 Output view is of shape ``(self.size,)`` (or 

4632 ``(np.ma.product(self.shape),)``). 

4633 

4634 Examples 

4635 -------- 

4636 >>> x = np.ma.array([[1,2,3],[4,5,6],[7,8,9]], mask=[0] + [1,0]*4) 

4637 >>> x 

4638 masked_array( 

4639 data=[[1, --, 3], 

4640 [--, 5, --], 

4641 [7, --, 9]], 

4642 mask=[[False, True, False], 

4643 [ True, False, True], 

4644 [False, True, False]], 

4645 fill_value=999999) 

4646 >>> x.ravel() 

4647 masked_array(data=[1, --, 3, --, 5, --, 7, --, 9], 

4648 mask=[False, True, False, True, False, True, False, True, 

4649 False], 

4650 fill_value=999999) 

4651 

4652 """ 

4653 # The order of _data and _mask could be different (it shouldn't be 

4654 # normally). Passing order `K` or `A` would be incorrect. 

4655 # So we ignore the mask memory order. 

4656 # TODO: We don't actually support K, so use A instead. We could 

4657 # try to guess this correct by sorting strides or deprecate. 

4658 if order in "kKaA": 

4659 order = "F" if self._data.flags.fnc else "C" 

4660 r = ndarray.ravel(self._data, order=order).view(type(self)) 

4661 r._update_from(self) 

4662 if self._mask is not nomask: 

4663 r._mask = ndarray.ravel(self._mask, order=order).reshape(r.shape) 

4664 else: 

4665 r._mask = nomask 

4666 return r 

4667 

4668 

4669 def reshape(self, *s, **kwargs): 

4670 """ 

4671 Give a new shape to the array without changing its data. 

4672 

4673 Returns a masked array containing the same data, but with a new shape. 

4674 The result is a view on the original array; if this is not possible, a 

4675 ValueError is raised. 

4676 

4677 Parameters 

4678 ---------- 

4679 shape : int or tuple of ints 

4680 The new shape should be compatible with the original shape. If an 

4681 integer is supplied, then the result will be a 1-D array of that 

4682 length. 

4683 order : {'C', 'F'}, optional 

4684 Determines whether the array data should be viewed as in C 

4685 (row-major) or FORTRAN (column-major) order. 

4686 

4687 Returns 

4688 ------- 

4689 reshaped_array : array 

4690 A new view on the array. 

4691 

4692 See Also 

4693 -------- 

4694 reshape : Equivalent function in the masked array module. 

4695 numpy.ndarray.reshape : Equivalent method on ndarray object. 

4696 numpy.reshape : Equivalent function in the NumPy module. 

4697 

4698 Notes 

4699 ----- 

4700 The reshaping operation cannot guarantee that a copy will not be made, 

4701 to modify the shape in place, use ``a.shape = s`` 

4702 

4703 Examples 

4704 -------- 

4705 >>> x = np.ma.array([[1,2],[3,4]], mask=[1,0,0,1]) 

4706 >>> x 

4707 masked_array( 

4708 data=[[--, 2], 

4709 [3, --]], 

4710 mask=[[ True, False], 

4711 [False, True]], 

4712 fill_value=999999) 

4713 >>> x = x.reshape((4,1)) 

4714 >>> x 

4715 masked_array( 

4716 data=[[--], 

4717 [2], 

4718 [3], 

4719 [--]], 

4720 mask=[[ True], 

4721 [False], 

4722 [False], 

4723 [ True]], 

4724 fill_value=999999) 

4725 

4726 """ 

4727 kwargs.update(order=kwargs.get('order', 'C')) 

4728 result = self._data.reshape(*s, **kwargs).view(type(self)) 

4729 result._update_from(self) 

4730 mask = self._mask 

4731 if mask is not nomask: 

4732 result._mask = mask.reshape(*s, **kwargs) 

4733 return result 

4734 

4735 def resize(self, newshape, refcheck=True, order=False): 

4736 """ 

4737 .. warning:: 

4738 

4739 This method does nothing, except raise a ValueError exception. A 

4740 masked array does not own its data and therefore cannot safely be 

4741 resized in place. Use the `numpy.ma.resize` function instead. 

4742 

4743 This method is difficult to implement safely and may be deprecated in 

4744 future releases of NumPy. 

4745 

4746 """ 

4747 # Note : the 'order' keyword looks broken, let's just drop it 

4748 errmsg = "A masked array does not own its data "\ 

4749 "and therefore cannot be resized.\n" \ 

4750 "Use the numpy.ma.resize function instead." 

4751 raise ValueError(errmsg) 

4752 

4753 def put(self, indices, values, mode='raise'): 

4754 """ 

4755 Set storage-indexed locations to corresponding values. 

4756 

4757 Sets self._data.flat[n] = values[n] for each n in indices. 

4758 If `values` is shorter than `indices` then it will repeat. 

4759 If `values` has some masked values, the initial mask is updated 

4760 in consequence, else the corresponding values are unmasked. 

4761 

4762 Parameters 

4763 ---------- 

4764 indices : 1-D array_like 

4765 Target indices, interpreted as integers. 

4766 values : array_like 

4767 Values to place in self._data copy at target indices. 

4768 mode : {'raise', 'wrap', 'clip'}, optional 

4769 Specifies how out-of-bounds indices will behave. 

4770 'raise' : raise an error. 

4771 'wrap' : wrap around. 

4772 'clip' : clip to the range. 

4773 

4774 Notes 

4775 ----- 

4776 `values` can be a scalar or length 1 array. 

4777 

4778 Examples 

4779 -------- 

4780 >>> x = np.ma.array([[1,2,3],[4,5,6],[7,8,9]], mask=[0] + [1,0]*4) 

4781 >>> x 

4782 masked_array( 

4783 data=[[1, --, 3], 

4784 [--, 5, --], 

4785 [7, --, 9]], 

4786 mask=[[False, True, False], 

4787 [ True, False, True], 

4788 [False, True, False]], 

4789 fill_value=999999) 

4790 >>> x.put([0,4,8],[10,20,30]) 

4791 >>> x 

4792 masked_array( 

4793 data=[[10, --, 3], 

4794 [--, 20, --], 

4795 [7, --, 30]], 

4796 mask=[[False, True, False], 

4797 [ True, False, True], 

4798 [False, True, False]], 

4799 fill_value=999999) 

4800 

4801 >>> x.put(4,999) 

4802 >>> x 

4803 masked_array( 

4804 data=[[10, --, 3], 

4805 [--, 999, --], 

4806 [7, --, 30]], 

4807 mask=[[False, True, False], 

4808 [ True, False, True], 

4809 [False, True, False]], 

4810 fill_value=999999) 

4811 

4812 """ 

4813 # Hard mask: Get rid of the values/indices that fall on masked data 

4814 if self._hardmask and self._mask is not nomask: 

4815 mask = self._mask[indices] 

4816 indices = narray(indices, copy=False) 

4817 values = narray(values, copy=False, subok=True) 

4818 values.resize(indices.shape) 

4819 indices = indices[~mask] 

4820 values = values[~mask] 

4821 

4822 self._data.put(indices, values, mode=mode) 

4823 

4824 # short circuit if neither self nor values are masked 

4825 if self._mask is nomask and getmask(values) is nomask: 

4826 return 

4827 

4828 m = getmaskarray(self) 

4829 

4830 if getmask(values) is nomask: 

4831 m.put(indices, False, mode=mode) 

4832 else: 

4833 m.put(indices, values._mask, mode=mode) 

4834 m = make_mask(m, copy=False, shrink=True) 

4835 self._mask = m 

4836 return 

4837 

4838 def ids(self): 

4839 """ 

4840 Return the addresses of the data and mask areas. 

4841 

4842 Parameters 

4843 ---------- 

4844 None 

4845 

4846 Examples 

4847 -------- 

4848 >>> x = np.ma.array([1, 2, 3], mask=[0, 1, 1]) 

4849 >>> x.ids() 

4850 (166670640, 166659832) # may vary 

4851 

4852 If the array has no mask, the address of `nomask` is returned. This address 

4853 is typically not close to the data in memory: 

4854 

4855 >>> x = np.ma.array([1, 2, 3]) 

4856 >>> x.ids() 

4857 (166691080, 3083169284) # may vary 

4858 

4859 """ 

4860 if self._mask is nomask: 

4861 return (self.ctypes.data, id(nomask)) 

4862 return (self.ctypes.data, self._mask.ctypes.data) 

4863 

4864 def iscontiguous(self): 

4865 """ 

4866 Return a boolean indicating whether the data is contiguous. 

4867 

4868 Parameters 

4869 ---------- 

4870 None 

4871 

4872 Examples 

4873 -------- 

4874 >>> x = np.ma.array([1, 2, 3]) 

4875 >>> x.iscontiguous() 

4876 True 

4877 

4878 `iscontiguous` returns one of the flags of the masked array: 

4879 

4880 >>> x.flags 

4881 C_CONTIGUOUS : True 

4882 F_CONTIGUOUS : True 

4883 OWNDATA : False 

4884 WRITEABLE : True 

4885 ALIGNED : True 

4886 WRITEBACKIFCOPY : False 

4887 

4888 """ 

4889 return self.flags['CONTIGUOUS'] 

4890 

4891 def all(self, axis=None, out=None, keepdims=np._NoValue): 

4892 """ 

4893 Returns True if all elements evaluate to True. 

4894 

4895 The output array is masked where all the values along the given axis 

4896 are masked: if the output would have been a scalar and that all the 

4897 values are masked, then the output is `masked`. 

4898 

4899 Refer to `numpy.all` for full documentation. 

4900 

4901 See Also 

4902 -------- 

4903 numpy.ndarray.all : corresponding function for ndarrays 

4904 numpy.all : equivalent function 

4905 

4906 Examples 

4907 -------- 

4908 >>> np.ma.array([1,2,3]).all() 

4909 True 

4910 >>> a = np.ma.array([1,2,3], mask=True) 

4911 >>> (a.all() is np.ma.masked) 

4912 True 

4913 

4914 """ 

4915 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

4916 

4917 mask = _check_mask_axis(self._mask, axis, **kwargs) 

4918 if out is None: 

4919 d = self.filled(True).all(axis=axis, **kwargs).view(type(self)) 

4920 if d.ndim: 

4921 d.__setmask__(mask) 

4922 elif mask: 

4923 return masked 

4924 return d 

4925 self.filled(True).all(axis=axis, out=out, **kwargs) 

4926 if isinstance(out, MaskedArray): 

4927 if out.ndim or mask: 

4928 out.__setmask__(mask) 

4929 return out 

4930 

4931 def any(self, axis=None, out=None, keepdims=np._NoValue): 

4932 """ 

4933 Returns True if any of the elements of `a` evaluate to True. 

4934 

4935 Masked values are considered as False during computation. 

4936 

4937 Refer to `numpy.any` for full documentation. 

4938 

4939 See Also 

4940 -------- 

4941 numpy.ndarray.any : corresponding function for ndarrays 

4942 numpy.any : equivalent function 

4943 

4944 """ 

4945 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

4946 

4947 mask = _check_mask_axis(self._mask, axis, **kwargs) 

4948 if out is None: 

4949 d = self.filled(False).any(axis=axis, **kwargs).view(type(self)) 

4950 if d.ndim: 

4951 d.__setmask__(mask) 

4952 elif mask: 

4953 d = masked 

4954 return d 

4955 self.filled(False).any(axis=axis, out=out, **kwargs) 

4956 if isinstance(out, MaskedArray): 

4957 if out.ndim or mask: 

4958 out.__setmask__(mask) 

4959 return out 

4960 

4961 def nonzero(self): 

4962 """ 

4963 Return the indices of unmasked elements that are not zero. 

4964 

4965 Returns a tuple of arrays, one for each dimension, containing the 

4966 indices of the non-zero elements in that dimension. The corresponding 

4967 non-zero values can be obtained with:: 

4968 

4969 a[a.nonzero()] 

4970 

4971 To group the indices by element, rather than dimension, use 

4972 instead:: 

4973 

4974 np.transpose(a.nonzero()) 

4975 

4976 The result of this is always a 2d array, with a row for each non-zero 

4977 element. 

4978 

4979 Parameters 

4980 ---------- 

4981 None 

4982 

4983 Returns 

4984 ------- 

4985 tuple_of_arrays : tuple 

4986 Indices of elements that are non-zero. 

4987 

4988 See Also 

4989 -------- 

4990 numpy.nonzero : 

4991 Function operating on ndarrays. 

4992 flatnonzero : 

4993 Return indices that are non-zero in the flattened version of the input 

4994 array. 

4995 numpy.ndarray.nonzero : 

4996 Equivalent ndarray method. 

4997 count_nonzero : 

4998 Counts the number of non-zero elements in the input array. 

4999 

5000 Examples 

5001 -------- 

5002 >>> import numpy.ma as ma 

5003 >>> x = ma.array(np.eye(3)) 

5004 >>> x 

5005 masked_array( 

5006 data=[[1., 0., 0.], 

5007 [0., 1., 0.], 

5008 [0., 0., 1.]], 

5009 mask=False, 

5010 fill_value=1e+20) 

5011 >>> x.nonzero() 

5012 (array([0, 1, 2]), array([0, 1, 2])) 

5013 

5014 Masked elements are ignored. 

5015 

5016 >>> x[1, 1] = ma.masked 

5017 >>> x 

5018 masked_array( 

5019 data=[[1.0, 0.0, 0.0], 

5020 [0.0, --, 0.0], 

5021 [0.0, 0.0, 1.0]], 

5022 mask=[[False, False, False], 

5023 [False, True, False], 

5024 [False, False, False]], 

5025 fill_value=1e+20) 

5026 >>> x.nonzero() 

5027 (array([0, 2]), array([0, 2])) 

5028 

5029 Indices can also be grouped by element. 

5030 

5031 >>> np.transpose(x.nonzero()) 

5032 array([[0, 0], 

5033 [2, 2]]) 

5034 

5035 A common use for ``nonzero`` is to find the indices of an array, where 

5036 a condition is True. Given an array `a`, the condition `a` > 3 is a 

5037 boolean array and since False is interpreted as 0, ma.nonzero(a > 3) 

5038 yields the indices of the `a` where the condition is true. 

5039 

5040 >>> a = ma.array([[1,2,3],[4,5,6],[7,8,9]]) 

5041 >>> a > 3 

5042 masked_array( 

5043 data=[[False, False, False], 

5044 [ True, True, True], 

5045 [ True, True, True]], 

5046 mask=False, 

5047 fill_value=True) 

5048 >>> ma.nonzero(a > 3) 

5049 (array([1, 1, 1, 2, 2, 2]), array([0, 1, 2, 0, 1, 2])) 

5050 

5051 The ``nonzero`` method of the condition array can also be called. 

5052 

5053 >>> (a > 3).nonzero() 

5054 (array([1, 1, 1, 2, 2, 2]), array([0, 1, 2, 0, 1, 2])) 

5055 

5056 """ 

5057 return narray(self.filled(0), copy=False).nonzero() 

5058 

5059 def trace(self, offset=0, axis1=0, axis2=1, dtype=None, out=None): 

5060 """ 

5061 (this docstring should be overwritten) 

5062 """ 

5063 #!!!: implement out + test! 

5064 m = self._mask 

5065 if m is nomask: 

5066 result = super().trace(offset=offset, axis1=axis1, axis2=axis2, 

5067 out=out) 

5068 return result.astype(dtype) 

5069 else: 

5070 D = self.diagonal(offset=offset, axis1=axis1, axis2=axis2) 

5071 return D.astype(dtype).filled(0).sum(axis=-1, out=out) 

5072 trace.__doc__ = ndarray.trace.__doc__ 

5073 

5074 def dot(self, b, out=None, strict=False): 

5075 """ 

5076 a.dot(b, out=None) 

5077 

5078 Masked dot product of two arrays. Note that `out` and `strict` are 

5079 located in different positions than in `ma.dot`. In order to 

5080 maintain compatibility with the functional version, it is 

5081 recommended that the optional arguments be treated as keyword only. 

5082 At some point that may be mandatory. 

5083 

5084 .. versionadded:: 1.10.0 

5085 

5086 Parameters 

5087 ---------- 

5088 b : masked_array_like 

5089 Inputs array. 

5090 out : masked_array, optional 

5091 Output argument. This must have the exact kind that would be 

5092 returned if it was not used. In particular, it must have the 

5093 right type, must be C-contiguous, and its dtype must be the 

5094 dtype that would be returned for `ma.dot(a,b)`. This is a 

5095 performance feature. Therefore, if these conditions are not 

5096 met, an exception is raised, instead of attempting to be 

5097 flexible. 

5098 strict : bool, optional 

5099 Whether masked data are propagated (True) or set to 0 (False) 

5100 for the computation. Default is False. Propagating the mask 

5101 means that if a masked value appears in a row or column, the 

5102 whole row or column is considered masked. 

5103 

5104 .. versionadded:: 1.10.2 

5105 

5106 See Also 

5107 -------- 

5108 numpy.ma.dot : equivalent function 

5109 

5110 """ 

5111 return dot(self, b, out=out, strict=strict) 

5112 

5113 def sum(self, axis=None, dtype=None, out=None, keepdims=np._NoValue): 

5114 """ 

5115 Return the sum of the array elements over the given axis. 

5116 

5117 Masked elements are set to 0 internally. 

5118 

5119 Refer to `numpy.sum` for full documentation. 

5120 

5121 See Also 

5122 -------- 

5123 numpy.ndarray.sum : corresponding function for ndarrays 

5124 numpy.sum : equivalent function 

5125 

5126 Examples 

5127 -------- 

5128 >>> x = np.ma.array([[1,2,3],[4,5,6],[7,8,9]], mask=[0] + [1,0]*4) 

5129 >>> x 

5130 masked_array( 

5131 data=[[1, --, 3], 

5132 [--, 5, --], 

5133 [7, --, 9]], 

5134 mask=[[False, True, False], 

5135 [ True, False, True], 

5136 [False, True, False]], 

5137 fill_value=999999) 

5138 >>> x.sum() 

5139 25 

5140 >>> x.sum(axis=1) 

5141 masked_array(data=[4, 5, 16], 

5142 mask=[False, False, False], 

5143 fill_value=999999) 

5144 >>> x.sum(axis=0) 

5145 masked_array(data=[8, 5, 12], 

5146 mask=[False, False, False], 

5147 fill_value=999999) 

5148 >>> print(type(x.sum(axis=0, dtype=np.int64)[0])) 

5149 <class 'numpy.int64'> 

5150 

5151 """ 

5152 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

5153 

5154 _mask = self._mask 

5155 newmask = _check_mask_axis(_mask, axis, **kwargs) 

5156 # No explicit output 

5157 if out is None: 

5158 result = self.filled(0).sum(axis, dtype=dtype, **kwargs) 

5159 rndim = getattr(result, 'ndim', 0) 

5160 if rndim: 

5161 result = result.view(type(self)) 

5162 result.__setmask__(newmask) 

5163 elif newmask: 

5164 result = masked 

5165 return result 

5166 # Explicit output 

5167 result = self.filled(0).sum(axis, dtype=dtype, out=out, **kwargs) 

5168 if isinstance(out, MaskedArray): 

5169 outmask = getmask(out) 

5170 if outmask is nomask: 

5171 outmask = out._mask = make_mask_none(out.shape) 

5172 outmask.flat = newmask 

5173 return out 

5174 

5175 def cumsum(self, axis=None, dtype=None, out=None): 

5176 """ 

5177 Return the cumulative sum of the array elements over the given axis. 

5178 

5179 Masked values are set to 0 internally during the computation. 

5180 However, their position is saved, and the result will be masked at 

5181 the same locations. 

5182 

5183 Refer to `numpy.cumsum` for full documentation. 

5184 

5185 Notes 

5186 ----- 

5187 The mask is lost if `out` is not a valid :class:`ma.MaskedArray` ! 

5188 

5189 Arithmetic is modular when using integer types, and no error is 

5190 raised on overflow. 

5191 

5192 See Also 

5193 -------- 

5194 numpy.ndarray.cumsum : corresponding function for ndarrays 

5195 numpy.cumsum : equivalent function 

5196 

5197 Examples 

5198 -------- 

5199 >>> marr = np.ma.array(np.arange(10), mask=[0,0,0,1,1,1,0,0,0,0]) 

5200 >>> marr.cumsum() 

5201 masked_array(data=[0, 1, 3, --, --, --, 9, 16, 24, 33], 

5202 mask=[False, False, False, True, True, True, False, False, 

5203 False, False], 

5204 fill_value=999999) 

5205 

5206 """ 

5207 result = self.filled(0).cumsum(axis=axis, dtype=dtype, out=out) 

5208 if out is not None: 

5209 if isinstance(out, MaskedArray): 

5210 out.__setmask__(self.mask) 

5211 return out 

5212 result = result.view(type(self)) 

5213 result.__setmask__(self._mask) 

5214 return result 

5215 

5216 def prod(self, axis=None, dtype=None, out=None, keepdims=np._NoValue): 

5217 """ 

5218 Return the product of the array elements over the given axis. 

5219 

5220 Masked elements are set to 1 internally for computation. 

5221 

5222 Refer to `numpy.prod` for full documentation. 

5223 

5224 Notes 

5225 ----- 

5226 Arithmetic is modular when using integer types, and no error is raised 

5227 on overflow. 

5228 

5229 See Also 

5230 -------- 

5231 numpy.ndarray.prod : corresponding function for ndarrays 

5232 numpy.prod : equivalent function 

5233 """ 

5234 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

5235 

5236 _mask = self._mask 

5237 newmask = _check_mask_axis(_mask, axis, **kwargs) 

5238 # No explicit output 

5239 if out is None: 

5240 result = self.filled(1).prod(axis, dtype=dtype, **kwargs) 

5241 rndim = getattr(result, 'ndim', 0) 

5242 if rndim: 

5243 result = result.view(type(self)) 

5244 result.__setmask__(newmask) 

5245 elif newmask: 

5246 result = masked 

5247 return result 

5248 # Explicit output 

5249 result = self.filled(1).prod(axis, dtype=dtype, out=out, **kwargs) 

5250 if isinstance(out, MaskedArray): 

5251 outmask = getmask(out) 

5252 if outmask is nomask: 

5253 outmask = out._mask = make_mask_none(out.shape) 

5254 outmask.flat = newmask 

5255 return out 

5256 product = prod 

5257 

5258 def cumprod(self, axis=None, dtype=None, out=None): 

5259 """ 

5260 Return the cumulative product of the array elements over the given axis. 

5261 

5262 Masked values are set to 1 internally during the computation. 

5263 However, their position is saved, and the result will be masked at 

5264 the same locations. 

5265 

5266 Refer to `numpy.cumprod` for full documentation. 

5267 

5268 Notes 

5269 ----- 

5270 The mask is lost if `out` is not a valid MaskedArray ! 

5271 

5272 Arithmetic is modular when using integer types, and no error is 

5273 raised on overflow. 

5274 

5275 See Also 

5276 -------- 

5277 numpy.ndarray.cumprod : corresponding function for ndarrays 

5278 numpy.cumprod : equivalent function 

5279 """ 

5280 result = self.filled(1).cumprod(axis=axis, dtype=dtype, out=out) 

5281 if out is not None: 

5282 if isinstance(out, MaskedArray): 

5283 out.__setmask__(self._mask) 

5284 return out 

5285 result = result.view(type(self)) 

5286 result.__setmask__(self._mask) 

5287 return result 

5288 

5289 def mean(self, axis=None, dtype=None, out=None, keepdims=np._NoValue): 

5290 """ 

5291 Returns the average of the array elements along given axis. 

5292 

5293 Masked entries are ignored, and result elements which are not 

5294 finite will be masked. 

5295 

5296 Refer to `numpy.mean` for full documentation. 

5297 

5298 See Also 

5299 -------- 

5300 numpy.ndarray.mean : corresponding function for ndarrays 

5301 numpy.mean : Equivalent function 

5302 numpy.ma.average : Weighted average. 

5303 

5304 Examples 

5305 -------- 

5306 >>> a = np.ma.array([1,2,3], mask=[False, False, True]) 

5307 >>> a 

5308 masked_array(data=[1, 2, --], 

5309 mask=[False, False, True], 

5310 fill_value=999999) 

5311 >>> a.mean() 

5312 1.5 

5313 

5314 """ 

5315 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

5316 if self._mask is nomask: 

5317 result = super().mean(axis=axis, dtype=dtype, **kwargs)[()] 

5318 else: 

5319 is_float16_result = False 

5320 if dtype is None: 

5321 if issubclass(self.dtype.type, (ntypes.integer, ntypes.bool_)): 

5322 dtype = mu.dtype('f8') 

5323 elif issubclass(self.dtype.type, ntypes.float16): 

5324 dtype = mu.dtype('f4') 

5325 is_float16_result = True 

5326 dsum = self.sum(axis=axis, dtype=dtype, **kwargs) 

5327 cnt = self.count(axis=axis, **kwargs) 

5328 if cnt.shape == () and (cnt == 0): 

5329 result = masked 

5330 elif is_float16_result: 

5331 result = self.dtype.type(dsum * 1. / cnt) 

5332 else: 

5333 result = dsum * 1. / cnt 

5334 if out is not None: 

5335 out.flat = result 

5336 if isinstance(out, MaskedArray): 

5337 outmask = getmask(out) 

5338 if outmask is nomask: 

5339 outmask = out._mask = make_mask_none(out.shape) 

5340 outmask.flat = getmask(result) 

5341 return out 

5342 return result 

5343 

5344 def anom(self, axis=None, dtype=None): 

5345 """ 

5346 Compute the anomalies (deviations from the arithmetic mean) 

5347 along the given axis. 

5348 

5349 Returns an array of anomalies, with the same shape as the input and 

5350 where the arithmetic mean is computed along the given axis. 

5351 

5352 Parameters 

5353 ---------- 

5354 axis : int, optional 

5355 Axis over which the anomalies are taken. 

5356 The default is to use the mean of the flattened array as reference. 

5357 dtype : dtype, optional 

5358 Type to use in computing the variance. For arrays of integer type 

5359 the default is float32; for arrays of float types it is the same as 

5360 the array type. 

5361 

5362 See Also 

5363 -------- 

5364 mean : Compute the mean of the array. 

5365 

5366 Examples 

5367 -------- 

5368 >>> a = np.ma.array([1,2,3]) 

5369 >>> a.anom() 

5370 masked_array(data=[-1., 0., 1.], 

5371 mask=False, 

5372 fill_value=1e+20) 

5373 

5374 """ 

5375 m = self.mean(axis, dtype) 

5376 if not axis: 

5377 return self - m 

5378 else: 

5379 return self - expand_dims(m, axis) 

5380 

5381 def var(self, axis=None, dtype=None, out=None, ddof=0, 

5382 keepdims=np._NoValue): 

5383 """ 

5384 Returns the variance of the array elements along given axis. 

5385 

5386 Masked entries are ignored, and result elements which are not 

5387 finite will be masked. 

5388 

5389 Refer to `numpy.var` for full documentation. 

5390 

5391 See Also 

5392 -------- 

5393 numpy.ndarray.var : corresponding function for ndarrays 

5394 numpy.var : Equivalent function 

5395 """ 

5396 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

5397 

5398 # Easy case: nomask, business as usual 

5399 if self._mask is nomask: 

5400 ret = super().var(axis=axis, dtype=dtype, out=out, ddof=ddof, 

5401 **kwargs)[()] 

5402 if out is not None: 

5403 if isinstance(out, MaskedArray): 

5404 out.__setmask__(nomask) 

5405 return out 

5406 return ret 

5407 

5408 # Some data are masked, yay! 

5409 cnt = self.count(axis=axis, **kwargs) - ddof 

5410 danom = self - self.mean(axis, dtype, keepdims=True) 

5411 if iscomplexobj(self): 

5412 danom = umath.absolute(danom) ** 2 

5413 else: 

5414 danom *= danom 

5415 dvar = divide(danom.sum(axis, **kwargs), cnt).view(type(self)) 

5416 # Apply the mask if it's not a scalar 

5417 if dvar.ndim: 

5418 dvar._mask = mask_or(self._mask.all(axis, **kwargs), (cnt <= 0)) 

5419 dvar._update_from(self) 

5420 elif getmask(dvar): 

5421 # Make sure that masked is returned when the scalar is masked. 

5422 dvar = masked 

5423 if out is not None: 

5424 if isinstance(out, MaskedArray): 

5425 out.flat = 0 

5426 out.__setmask__(True) 

5427 elif out.dtype.kind in 'biu': 

5428 errmsg = "Masked data information would be lost in one or "\ 

5429 "more location." 

5430 raise MaskError(errmsg) 

5431 else: 

5432 out.flat = np.nan 

5433 return out 

5434 # In case with have an explicit output 

5435 if out is not None: 

5436 # Set the data 

5437 out.flat = dvar 

5438 # Set the mask if needed 

5439 if isinstance(out, MaskedArray): 

5440 out.__setmask__(dvar.mask) 

5441 return out 

5442 return dvar 

5443 var.__doc__ = np.var.__doc__ 

5444 

5445 def std(self, axis=None, dtype=None, out=None, ddof=0, 

5446 keepdims=np._NoValue): 

5447 """ 

5448 Returns the standard deviation of the array elements along given axis. 

5449 

5450 Masked entries are ignored. 

5451 

5452 Refer to `numpy.std` for full documentation. 

5453 

5454 See Also 

5455 -------- 

5456 numpy.ndarray.std : corresponding function for ndarrays 

5457 numpy.std : Equivalent function 

5458 """ 

5459 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

5460 

5461 dvar = self.var(axis, dtype, out, ddof, **kwargs) 

5462 if dvar is not masked: 

5463 if out is not None: 

5464 np.power(out, 0.5, out=out, casting='unsafe') 

5465 return out 

5466 dvar = sqrt(dvar) 

5467 return dvar 

5468 

5469 def round(self, decimals=0, out=None): 

5470 """ 

5471 Return each element rounded to the given number of decimals. 

5472 

5473 Refer to `numpy.around` for full documentation. 

5474 

5475 See Also 

5476 -------- 

5477 numpy.ndarray.round : corresponding function for ndarrays 

5478 numpy.around : equivalent function 

5479 """ 

5480 result = self._data.round(decimals=decimals, out=out).view(type(self)) 

5481 if result.ndim > 0: 

5482 result._mask = self._mask 

5483 result._update_from(self) 

5484 elif self._mask: 

5485 # Return masked when the scalar is masked 

5486 result = masked 

5487 # No explicit output: we're done 

5488 if out is None: 

5489 return result 

5490 if isinstance(out, MaskedArray): 

5491 out.__setmask__(self._mask) 

5492 return out 

5493 

5494 def argsort(self, axis=np._NoValue, kind=None, order=None, 

5495 endwith=True, fill_value=None): 

5496 """ 

5497 Return an ndarray of indices that sort the array along the 

5498 specified axis. Masked values are filled beforehand to 

5499 `fill_value`. 

5500 

5501 Parameters 

5502 ---------- 

5503 axis : int, optional 

5504 Axis along which to sort. If None, the default, the flattened array 

5505 is used. 

5506 

5507 .. versionchanged:: 1.13.0 

5508 Previously, the default was documented to be -1, but that was 

5509 in error. At some future date, the default will change to -1, as 

5510 originally intended. 

5511 Until then, the axis should be given explicitly when 

5512 ``arr.ndim > 1``, to avoid a FutureWarning. 

5513 kind : {'quicksort', 'mergesort', 'heapsort', 'stable'}, optional 

5514 The sorting algorithm used. 

5515 order : list, optional 

5516 When `a` is an array with fields defined, this argument specifies 

5517 which fields to compare first, second, etc. Not all fields need be 

5518 specified. 

5519 endwith : {True, False}, optional 

5520 Whether missing values (if any) should be treated as the largest values 

5521 (True) or the smallest values (False) 

5522 When the array contains unmasked values at the same extremes of the 

5523 datatype, the ordering of these values and the masked values is 

5524 undefined. 

5525 fill_value : scalar or None, optional 

5526 Value used internally for the masked values. 

5527 If ``fill_value`` is not None, it supersedes ``endwith``. 

5528 

5529 Returns 

5530 ------- 

5531 index_array : ndarray, int 

5532 Array of indices that sort `a` along the specified axis. 

5533 In other words, ``a[index_array]`` yields a sorted `a`. 

5534 

5535 See Also 

5536 -------- 

5537 ma.MaskedArray.sort : Describes sorting algorithms used. 

5538 lexsort : Indirect stable sort with multiple keys. 

5539 numpy.ndarray.sort : Inplace sort. 

5540 

5541 Notes 

5542 ----- 

5543 See `sort` for notes on the different sorting algorithms. 

5544 

5545 Examples 

5546 -------- 

5547 >>> a = np.ma.array([3,2,1], mask=[False, False, True]) 

5548 >>> a 

5549 masked_array(data=[3, 2, --], 

5550 mask=[False, False, True], 

5551 fill_value=999999) 

5552 >>> a.argsort() 

5553 array([1, 0, 2]) 

5554 

5555 """ 

5556 

5557 # 2017-04-11, Numpy 1.13.0, gh-8701: warn on axis default 

5558 if axis is np._NoValue: 

5559 axis = _deprecate_argsort_axis(self) 

5560 

5561 if fill_value is None: 

5562 if endwith: 

5563 # nan > inf 

5564 if np.issubdtype(self.dtype, np.floating): 

5565 fill_value = np.nan 

5566 else: 

5567 fill_value = minimum_fill_value(self) 

5568 else: 

5569 fill_value = maximum_fill_value(self) 

5570 

5571 filled = self.filled(fill_value) 

5572 return filled.argsort(axis=axis, kind=kind, order=order) 

5573 

5574 def argmin(self, axis=None, fill_value=None, out=None, *, 

5575 keepdims=np._NoValue): 

5576 """ 

5577 Return array of indices to the minimum values along the given axis. 

5578 

5579 Parameters 

5580 ---------- 

5581 axis : {None, integer} 

5582 If None, the index is into the flattened array, otherwise along 

5583 the specified axis 

5584 fill_value : scalar or None, optional 

5585 Value used to fill in the masked values. If None, the output of 

5586 minimum_fill_value(self._data) is used instead. 

5587 out : {None, array}, optional 

5588 Array into which the result can be placed. Its type is preserved 

5589 and it must be of the right shape to hold the output. 

5590 

5591 Returns 

5592 ------- 

5593 ndarray or scalar 

5594 If multi-dimension input, returns a new ndarray of indices to the 

5595 minimum values along the given axis. Otherwise, returns a scalar 

5596 of index to the minimum values along the given axis. 

5597 

5598 Examples 

5599 -------- 

5600 >>> x = np.ma.array(np.arange(4), mask=[1,1,0,0]) 

5601 >>> x.shape = (2,2) 

5602 >>> x 

5603 masked_array( 

5604 data=[[--, --], 

5605 [2, 3]], 

5606 mask=[[ True, True], 

5607 [False, False]], 

5608 fill_value=999999) 

5609 >>> x.argmin(axis=0, fill_value=-1) 

5610 array([0, 0]) 

5611 >>> x.argmin(axis=0, fill_value=9) 

5612 array([1, 1]) 

5613 

5614 """ 

5615 if fill_value is None: 

5616 fill_value = minimum_fill_value(self) 

5617 d = self.filled(fill_value).view(ndarray) 

5618 keepdims = False if keepdims is np._NoValue else bool(keepdims) 

5619 return d.argmin(axis, out=out, keepdims=keepdims) 

5620 

5621 def argmax(self, axis=None, fill_value=None, out=None, *, 

5622 keepdims=np._NoValue): 

5623 """ 

5624 Returns array of indices of the maximum values along the given axis. 

5625 Masked values are treated as if they had the value fill_value. 

5626 

5627 Parameters 

5628 ---------- 

5629 axis : {None, integer} 

5630 If None, the index is into the flattened array, otherwise along 

5631 the specified axis 

5632 fill_value : scalar or None, optional 

5633 Value used to fill in the masked values. If None, the output of 

5634 maximum_fill_value(self._data) is used instead. 

5635 out : {None, array}, optional 

5636 Array into which the result can be placed. Its type is preserved 

5637 and it must be of the right shape to hold the output. 

5638 

5639 Returns 

5640 ------- 

5641 index_array : {integer_array} 

5642 

5643 Examples 

5644 -------- 

5645 >>> a = np.arange(6).reshape(2,3) 

5646 >>> a.argmax() 

5647 5 

5648 >>> a.argmax(0) 

5649 array([1, 1, 1]) 

5650 >>> a.argmax(1) 

5651 array([2, 2]) 

5652 

5653 """ 

5654 if fill_value is None: 

5655 fill_value = maximum_fill_value(self._data) 

5656 d = self.filled(fill_value).view(ndarray) 

5657 keepdims = False if keepdims is np._NoValue else bool(keepdims) 

5658 return d.argmax(axis, out=out, keepdims=keepdims) 

5659 

5660 def sort(self, axis=-1, kind=None, order=None, 

5661 endwith=True, fill_value=None): 

5662 """ 

5663 Sort the array, in-place 

5664 

5665 Parameters 

5666 ---------- 

5667 a : array_like 

5668 Array to be sorted. 

5669 axis : int, optional 

5670 Axis along which to sort. If None, the array is flattened before 

5671 sorting. The default is -1, which sorts along the last axis. 

5672 kind : {'quicksort', 'mergesort', 'heapsort', 'stable'}, optional 

5673 The sorting algorithm used. 

5674 order : list, optional 

5675 When `a` is a structured array, this argument specifies which fields 

5676 to compare first, second, and so on. This list does not need to 

5677 include all of the fields. 

5678 endwith : {True, False}, optional 

5679 Whether missing values (if any) should be treated as the largest values 

5680 (True) or the smallest values (False) 

5681 When the array contains unmasked values sorting at the same extremes of the 

5682 datatype, the ordering of these values and the masked values is 

5683 undefined. 

5684 fill_value : scalar or None, optional 

5685 Value used internally for the masked values. 

5686 If ``fill_value`` is not None, it supersedes ``endwith``. 

5687 

5688 Returns 

5689 ------- 

5690 sorted_array : ndarray 

5691 Array of the same type and shape as `a`. 

5692 

5693 See Also 

5694 -------- 

5695 numpy.ndarray.sort : Method to sort an array in-place. 

5696 argsort : Indirect sort. 

5697 lexsort : Indirect stable sort on multiple keys. 

5698 searchsorted : Find elements in a sorted array. 

5699 

5700 Notes 

5701 ----- 

5702 See ``sort`` for notes on the different sorting algorithms. 

5703 

5704 Examples 

5705 -------- 

5706 >>> a = np.ma.array([1, 2, 5, 4, 3],mask=[0, 1, 0, 1, 0]) 

5707 >>> # Default 

5708 >>> a.sort() 

5709 >>> a 

5710 masked_array(data=[1, 3, 5, --, --], 

5711 mask=[False, False, False, True, True], 

5712 fill_value=999999) 

5713 

5714 >>> a = np.ma.array([1, 2, 5, 4, 3],mask=[0, 1, 0, 1, 0]) 

5715 >>> # Put missing values in the front 

5716 >>> a.sort(endwith=False) 

5717 >>> a 

5718 masked_array(data=[--, --, 1, 3, 5], 

5719 mask=[ True, True, False, False, False], 

5720 fill_value=999999) 

5721 

5722 >>> a = np.ma.array([1, 2, 5, 4, 3],mask=[0, 1, 0, 1, 0]) 

5723 >>> # fill_value takes over endwith 

5724 >>> a.sort(endwith=False, fill_value=3) 

5725 >>> a 

5726 masked_array(data=[1, --, --, 3, 5], 

5727 mask=[False, True, True, False, False], 

5728 fill_value=999999) 

5729 

5730 """ 

5731 if self._mask is nomask: 

5732 ndarray.sort(self, axis=axis, kind=kind, order=order) 

5733 return 

5734 

5735 if self is masked: 

5736 return 

5737 

5738 sidx = self.argsort(axis=axis, kind=kind, order=order, 

5739 fill_value=fill_value, endwith=endwith) 

5740 

5741 self[...] = np.take_along_axis(self, sidx, axis=axis) 

5742 

5743 def min(self, axis=None, out=None, fill_value=None, keepdims=np._NoValue): 

5744 """ 

5745 Return the minimum along a given axis. 

5746 

5747 Parameters 

5748 ---------- 

5749 axis : None or int or tuple of ints, optional 

5750 Axis along which to operate. By default, ``axis`` is None and the 

5751 flattened input is used. 

5752 .. versionadded:: 1.7.0 

5753 If this is a tuple of ints, the minimum is selected over multiple 

5754 axes, instead of a single axis or all the axes as before. 

5755 out : array_like, optional 

5756 Alternative output array in which to place the result. Must be of 

5757 the same shape and buffer length as the expected output. 

5758 fill_value : scalar or None, optional 

5759 Value used to fill in the masked values. 

5760 If None, use the output of `minimum_fill_value`. 

5761 keepdims : bool, optional 

5762 If this is set to True, the axes which are reduced are left 

5763 in the result as dimensions with size one. With this option, 

5764 the result will broadcast correctly against the array. 

5765 

5766 Returns 

5767 ------- 

5768 amin : array_like 

5769 New array holding the result. 

5770 If ``out`` was specified, ``out`` is returned. 

5771 

5772 See Also 

5773 -------- 

5774 ma.minimum_fill_value 

5775 Returns the minimum filling value for a given datatype. 

5776 

5777 Examples 

5778 -------- 

5779 >>> import numpy.ma as ma 

5780 >>> x = [[1., -2., 3.], [0.2, -0.7, 0.1]] 

5781 >>> mask = [[1, 1, 0], [0, 0, 1]] 

5782 >>> masked_x = ma.masked_array(x, mask) 

5783 >>> masked_x 

5784 masked_array( 

5785 data=[[--, --, 3.0], 

5786 [0.2, -0.7, --]], 

5787 mask=[[ True, True, False], 

5788 [False, False, True]], 

5789 fill_value=1e+20) 

5790 >>> ma.min(masked_x) 

5791 -0.7 

5792 >>> ma.min(masked_x, axis=-1) 

5793 masked_array(data=[3.0, -0.7], 

5794 mask=[False, False], 

5795 fill_value=1e+20) 

5796 >>> ma.min(masked_x, axis=0, keepdims=True) 

5797 masked_array(data=[[0.2, -0.7, 3.0]], 

5798 mask=[[False, False, False]], 

5799 fill_value=1e+20) 

5800 >>> mask = [[1, 1, 1,], [1, 1, 1]] 

5801 >>> masked_x = ma.masked_array(x, mask) 

5802 >>> ma.min(masked_x, axis=0) 

5803 masked_array(data=[--, --, --], 

5804 mask=[ True, True, True], 

5805 fill_value=1e+20, 

5806 dtype=float64) 

5807 """ 

5808 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

5809 

5810 _mask = self._mask 

5811 newmask = _check_mask_axis(_mask, axis, **kwargs) 

5812 if fill_value is None: 

5813 fill_value = minimum_fill_value(self) 

5814 # No explicit output 

5815 if out is None: 

5816 result = self.filled(fill_value).min( 

5817 axis=axis, out=out, **kwargs).view(type(self)) 

5818 if result.ndim: 

5819 # Set the mask 

5820 result.__setmask__(newmask) 

5821 # Get rid of Infs 

5822 if newmask.ndim: 

5823 np.copyto(result, result.fill_value, where=newmask) 

5824 elif newmask: 

5825 result = masked 

5826 return result 

5827 # Explicit output 

5828 result = self.filled(fill_value).min(axis=axis, out=out, **kwargs) 

5829 if isinstance(out, MaskedArray): 

5830 outmask = getmask(out) 

5831 if outmask is nomask: 

5832 outmask = out._mask = make_mask_none(out.shape) 

5833 outmask.flat = newmask 

5834 else: 

5835 if out.dtype.kind in 'biu': 

5836 errmsg = "Masked data information would be lost in one or more"\ 

5837 " location." 

5838 raise MaskError(errmsg) 

5839 np.copyto(out, np.nan, where=newmask) 

5840 return out 

5841 

5842 def max(self, axis=None, out=None, fill_value=None, keepdims=np._NoValue): 

5843 """ 

5844 Return the maximum along a given axis. 

5845 

5846 Parameters 

5847 ---------- 

5848 axis : None or int or tuple of ints, optional 

5849 Axis along which to operate. By default, ``axis`` is None and the 

5850 flattened input is used. 

5851 .. versionadded:: 1.7.0 

5852 If this is a tuple of ints, the maximum is selected over multiple 

5853 axes, instead of a single axis or all the axes as before. 

5854 out : array_like, optional 

5855 Alternative output array in which to place the result. Must 

5856 be of the same shape and buffer length as the expected output. 

5857 fill_value : scalar or None, optional 

5858 Value used to fill in the masked values. 

5859 If None, use the output of maximum_fill_value(). 

5860 keepdims : bool, optional 

5861 If this is set to True, the axes which are reduced are left 

5862 in the result as dimensions with size one. With this option, 

5863 the result will broadcast correctly against the array. 

5864 

5865 Returns 

5866 ------- 

5867 amax : array_like 

5868 New array holding the result. 

5869 If ``out`` was specified, ``out`` is returned. 

5870 

5871 See Also 

5872 -------- 

5873 ma.maximum_fill_value 

5874 Returns the maximum filling value for a given datatype. 

5875 

5876 Examples 

5877 -------- 

5878 >>> import numpy.ma as ma 

5879 >>> x = [[-1., 2.5], [4., -2.], [3., 0.]] 

5880 >>> mask = [[0, 0], [1, 0], [1, 0]] 

5881 >>> masked_x = ma.masked_array(x, mask) 

5882 >>> masked_x 

5883 masked_array( 

5884 data=[[-1.0, 2.5], 

5885 [--, -2.0], 

5886 [--, 0.0]], 

5887 mask=[[False, False], 

5888 [ True, False], 

5889 [ True, False]], 

5890 fill_value=1e+20) 

5891 >>> ma.max(masked_x) 

5892 2.5 

5893 >>> ma.max(masked_x, axis=0) 

5894 masked_array(data=[-1.0, 2.5], 

5895 mask=[False, False], 

5896 fill_value=1e+20) 

5897 >>> ma.max(masked_x, axis=1, keepdims=True) 

5898 masked_array( 

5899 data=[[2.5], 

5900 [-2.0], 

5901 [0.0]], 

5902 mask=[[False], 

5903 [False], 

5904 [False]], 

5905 fill_value=1e+20) 

5906 >>> mask = [[1, 1], [1, 1], [1, 1]] 

5907 >>> masked_x = ma.masked_array(x, mask) 

5908 >>> ma.max(masked_x, axis=1) 

5909 masked_array(data=[--, --, --], 

5910 mask=[ True, True, True], 

5911 fill_value=1e+20, 

5912 dtype=float64) 

5913 """ 

5914 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

5915 

5916 _mask = self._mask 

5917 newmask = _check_mask_axis(_mask, axis, **kwargs) 

5918 if fill_value is None: 

5919 fill_value = maximum_fill_value(self) 

5920 # No explicit output 

5921 if out is None: 

5922 result = self.filled(fill_value).max( 

5923 axis=axis, out=out, **kwargs).view(type(self)) 

5924 if result.ndim: 

5925 # Set the mask 

5926 result.__setmask__(newmask) 

5927 # Get rid of Infs 

5928 if newmask.ndim: 

5929 np.copyto(result, result.fill_value, where=newmask) 

5930 elif newmask: 

5931 result = masked 

5932 return result 

5933 # Explicit output 

5934 result = self.filled(fill_value).max(axis=axis, out=out, **kwargs) 

5935 if isinstance(out, MaskedArray): 

5936 outmask = getmask(out) 

5937 if outmask is nomask: 

5938 outmask = out._mask = make_mask_none(out.shape) 

5939 outmask.flat = newmask 

5940 else: 

5941 

5942 if out.dtype.kind in 'biu': 

5943 errmsg = "Masked data information would be lost in one or more"\ 

5944 " location." 

5945 raise MaskError(errmsg) 

5946 np.copyto(out, np.nan, where=newmask) 

5947 return out 

5948 

5949 def ptp(self, axis=None, out=None, fill_value=None, keepdims=False): 

5950 """ 

5951 Return (maximum - minimum) along the given dimension 

5952 (i.e. peak-to-peak value). 

5953 

5954 .. warning:: 

5955 `ptp` preserves the data type of the array. This means the 

5956 return value for an input of signed integers with n bits 

5957 (e.g. `np.int8`, `np.int16`, etc) is also a signed integer 

5958 with n bits. In that case, peak-to-peak values greater than 

5959 ``2**(n-1)-1`` will be returned as negative values. An example 

5960 with a work-around is shown below. 

5961 

5962 Parameters 

5963 ---------- 

5964 axis : {None, int}, optional 

5965 Axis along which to find the peaks. If None (default) the 

5966 flattened array is used. 

5967 out : {None, array_like}, optional 

5968 Alternative output array in which to place the result. It must 

5969 have the same shape and buffer length as the expected output 

5970 but the type will be cast if necessary. 

5971 fill_value : scalar or None, optional 

5972 Value used to fill in the masked values. 

5973 keepdims : bool, optional 

5974 If this is set to True, the axes which are reduced are left 

5975 in the result as dimensions with size one. With this option, 

5976 the result will broadcast correctly against the array. 

5977 

5978 Returns 

5979 ------- 

5980 ptp : ndarray. 

5981 A new array holding the result, unless ``out`` was 

5982 specified, in which case a reference to ``out`` is returned. 

5983 

5984 Examples 

5985 -------- 

5986 >>> x = np.ma.MaskedArray([[4, 9, 2, 10], 

5987 ... [6, 9, 7, 12]]) 

5988 

5989 >>> x.ptp(axis=1) 

5990 masked_array(data=[8, 6], 

5991 mask=False, 

5992 fill_value=999999) 

5993 

5994 >>> x.ptp(axis=0) 

5995 masked_array(data=[2, 0, 5, 2], 

5996 mask=False, 

5997 fill_value=999999) 

5998 

5999 >>> x.ptp() 

6000 10 

6001 

6002 This example shows that a negative value can be returned when 

6003 the input is an array of signed integers. 

6004 

6005 >>> y = np.ma.MaskedArray([[1, 127], 

6006 ... [0, 127], 

6007 ... [-1, 127], 

6008 ... [-2, 127]], dtype=np.int8) 

6009 >>> y.ptp(axis=1) 

6010 masked_array(data=[ 126, 127, -128, -127], 

6011 mask=False, 

6012 fill_value=999999, 

6013 dtype=int8) 

6014 

6015 A work-around is to use the `view()` method to view the result as 

6016 unsigned integers with the same bit width: 

6017 

6018 >>> y.ptp(axis=1).view(np.uint8) 

6019 masked_array(data=[126, 127, 128, 129], 

6020 mask=False, 

6021 fill_value=999999, 

6022 dtype=uint8) 

6023 """ 

6024 if out is None: 

6025 result = self.max(axis=axis, fill_value=fill_value, 

6026 keepdims=keepdims) 

6027 result -= self.min(axis=axis, fill_value=fill_value, 

6028 keepdims=keepdims) 

6029 return result 

6030 out.flat = self.max(axis=axis, out=out, fill_value=fill_value, 

6031 keepdims=keepdims) 

6032 min_value = self.min(axis=axis, fill_value=fill_value, 

6033 keepdims=keepdims) 

6034 np.subtract(out, min_value, out=out, casting='unsafe') 

6035 return out 

6036 

6037 def partition(self, *args, **kwargs): 

6038 warnings.warn("Warning: 'partition' will ignore the 'mask' " 

6039 f"of the {self.__class__.__name__}.", 

6040 stacklevel=2) 

6041 return super().partition(*args, **kwargs) 

6042 

6043 def argpartition(self, *args, **kwargs): 

6044 warnings.warn("Warning: 'argpartition' will ignore the 'mask' " 

6045 f"of the {self.__class__.__name__}.", 

6046 stacklevel=2) 

6047 return super().argpartition(*args, **kwargs) 

6048 

6049 def take(self, indices, axis=None, out=None, mode='raise'): 

6050 """ 

6051 """ 

6052 (_data, _mask) = (self._data, self._mask) 

6053 cls = type(self) 

6054 # Make sure the indices are not masked 

6055 maskindices = getmask(indices) 

6056 if maskindices is not nomask: 

6057 indices = indices.filled(0) 

6058 # Get the data, promoting scalars to 0d arrays with [...] so that 

6059 # .view works correctly 

6060 if out is None: 

6061 out = _data.take(indices, axis=axis, mode=mode)[...].view(cls) 

6062 else: 

6063 np.take(_data, indices, axis=axis, mode=mode, out=out) 

6064 # Get the mask 

6065 if isinstance(out, MaskedArray): 

6066 if _mask is nomask: 

6067 outmask = maskindices 

6068 else: 

6069 outmask = _mask.take(indices, axis=axis, mode=mode) 

6070 outmask |= maskindices 

6071 out.__setmask__(outmask) 

6072 # demote 0d arrays back to scalars, for consistency with ndarray.take 

6073 return out[()] 

6074 

6075 # Array methods 

6076 copy = _arraymethod('copy') 

6077 diagonal = _arraymethod('diagonal') 

6078 flatten = _arraymethod('flatten') 

6079 repeat = _arraymethod('repeat') 

6080 squeeze = _arraymethod('squeeze') 

6081 swapaxes = _arraymethod('swapaxes') 

6082 T = property(fget=lambda self: self.transpose()) 

6083 transpose = _arraymethod('transpose') 

6084 

6085 def tolist(self, fill_value=None): 

6086 """ 

6087 Return the data portion of the masked array as a hierarchical Python list. 

6088 

6089 Data items are converted to the nearest compatible Python type. 

6090 Masked values are converted to `fill_value`. If `fill_value` is None, 

6091 the corresponding entries in the output list will be ``None``. 

6092 

6093 Parameters 

6094 ---------- 

6095 fill_value : scalar, optional 

6096 The value to use for invalid entries. Default is None. 

6097 

6098 Returns 

6099 ------- 

6100 result : list 

6101 The Python list representation of the masked array. 

6102 

6103 Examples 

6104 -------- 

6105 >>> x = np.ma.array([[1,2,3], [4,5,6], [7,8,9]], mask=[0] + [1,0]*4) 

6106 >>> x.tolist() 

6107 [[1, None, 3], [None, 5, None], [7, None, 9]] 

6108 >>> x.tolist(-999) 

6109 [[1, -999, 3], [-999, 5, -999], [7, -999, 9]] 

6110 

6111 """ 

6112 _mask = self._mask 

6113 # No mask ? Just return .data.tolist ? 

6114 if _mask is nomask: 

6115 return self._data.tolist() 

6116 # Explicit fill_value: fill the array and get the list 

6117 if fill_value is not None: 

6118 return self.filled(fill_value).tolist() 

6119 # Structured array. 

6120 names = self.dtype.names 

6121 if names: 

6122 result = self._data.astype([(_, object) for _ in names]) 

6123 for n in names: 

6124 result[n][_mask[n]] = None 

6125 return result.tolist() 

6126 # Standard arrays. 

6127 if _mask is nomask: 

6128 return [None] 

6129 # Set temps to save time when dealing w/ marrays. 

6130 inishape = self.shape 

6131 result = np.array(self._data.ravel(), dtype=object) 

6132 result[_mask.ravel()] = None 

6133 result.shape = inishape 

6134 return result.tolist() 

6135 

6136 def tostring(self, fill_value=None, order='C'): 

6137 r""" 

6138 A compatibility alias for `tobytes`, with exactly the same behavior. 

6139 

6140 Despite its name, it returns `bytes` not `str`\ s. 

6141 

6142 .. deprecated:: 1.19.0 

6143 """ 

6144 # 2020-03-30, Numpy 1.19.0 

6145 warnings.warn( 

6146 "tostring() is deprecated. Use tobytes() instead.", 

6147 DeprecationWarning, stacklevel=2) 

6148 

6149 return self.tobytes(fill_value, order=order) 

6150 

6151 def tobytes(self, fill_value=None, order='C'): 

6152 """ 

6153 Return the array data as a string containing the raw bytes in the array. 

6154 

6155 The array is filled with a fill value before the string conversion. 

6156 

6157 .. versionadded:: 1.9.0 

6158 

6159 Parameters 

6160 ---------- 

6161 fill_value : scalar, optional 

6162 Value used to fill in the masked values. Default is None, in which 

6163 case `MaskedArray.fill_value` is used. 

6164 order : {'C','F','A'}, optional 

6165 Order of the data item in the copy. Default is 'C'. 

6166 

6167 - 'C' -- C order (row major). 

6168 - 'F' -- Fortran order (column major). 

6169 - 'A' -- Any, current order of array. 

6170 - None -- Same as 'A'. 

6171 

6172 See Also 

6173 -------- 

6174 numpy.ndarray.tobytes 

6175 tolist, tofile 

6176 

6177 Notes 

6178 ----- 

6179 As for `ndarray.tobytes`, information about the shape, dtype, etc., 

6180 but also about `fill_value`, will be lost. 

6181 

6182 Examples 

6183 -------- 

6184 >>> x = np.ma.array(np.array([[1, 2], [3, 4]]), mask=[[0, 1], [1, 0]]) 

6185 >>> x.tobytes() 

6186 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' 

6187 

6188 """ 

6189 return self.filled(fill_value).tobytes(order=order) 

6190 

6191 def tofile(self, fid, sep="", format="%s"): 

6192 """ 

6193 Save a masked array to a file in binary format. 

6194 

6195 .. warning:: 

6196 This function is not implemented yet. 

6197 

6198 Raises 

6199 ------ 

6200 NotImplementedError 

6201 When `tofile` is called. 

6202 

6203 """ 

6204 raise NotImplementedError("MaskedArray.tofile() not implemented yet.") 

6205 

6206 def toflex(self): 

6207 """ 

6208 Transforms a masked array into a flexible-type array. 

6209 

6210 The flexible type array that is returned will have two fields: 

6211 

6212 * the ``_data`` field stores the ``_data`` part of the array. 

6213 * the ``_mask`` field stores the ``_mask`` part of the array. 

6214 

6215 Parameters 

6216 ---------- 

6217 None 

6218 

6219 Returns 

6220 ------- 

6221 record : ndarray 

6222 A new flexible-type `ndarray` with two fields: the first element 

6223 containing a value, the second element containing the corresponding 

6224 mask boolean. The returned record shape matches self.shape. 

6225 

6226 Notes 

6227 ----- 

6228 A side-effect of transforming a masked array into a flexible `ndarray` is 

6229 that meta information (``fill_value``, ...) will be lost. 

6230 

6231 Examples 

6232 -------- 

6233 >>> x = np.ma.array([[1,2,3],[4,5,6],[7,8,9]], mask=[0] + [1,0]*4) 

6234 >>> x 

6235 masked_array( 

6236 data=[[1, --, 3], 

6237 [--, 5, --], 

6238 [7, --, 9]], 

6239 mask=[[False, True, False], 

6240 [ True, False, True], 

6241 [False, True, False]], 

6242 fill_value=999999) 

6243 >>> x.toflex() 

6244 array([[(1, False), (2, True), (3, False)], 

6245 [(4, True), (5, False), (6, True)], 

6246 [(7, False), (8, True), (9, False)]], 

6247 dtype=[('_data', '<i8'), ('_mask', '?')]) 

6248 

6249 """ 

6250 # Get the basic dtype. 

6251 ddtype = self.dtype 

6252 # Make sure we have a mask 

6253 _mask = self._mask 

6254 if _mask is None: 

6255 _mask = make_mask_none(self.shape, ddtype) 

6256 # And get its dtype 

6257 mdtype = self._mask.dtype 

6258 

6259 record = np.ndarray(shape=self.shape, 

6260 dtype=[('_data', ddtype), ('_mask', mdtype)]) 

6261 record['_data'] = self._data 

6262 record['_mask'] = self._mask 

6263 return record 

6264 torecords = toflex 

6265 

6266 # Pickling 

6267 def __getstate__(self): 

6268 """Return the internal state of the masked array, for pickling 

6269 purposes. 

6270 

6271 """ 

6272 cf = 'CF'[self.flags.fnc] 

6273 data_state = super().__reduce__()[2] 

6274 return data_state + (getmaskarray(self).tobytes(cf), self._fill_value) 

6275 

6276 def __setstate__(self, state): 

6277 """Restore the internal state of the masked array, for 

6278 pickling purposes. ``state`` is typically the output of the 

6279 ``__getstate__`` output, and is a 5-tuple: 

6280 

6281 - class name 

6282 - a tuple giving the shape of the data 

6283 - a typecode for the data 

6284 - a binary string for the data 

6285 - a binary string for the mask. 

6286 

6287 """ 

6288 (_, shp, typ, isf, raw, msk, flv) = state 

6289 super().__setstate__((shp, typ, isf, raw)) 

6290 self._mask.__setstate__((shp, make_mask_descr(typ), isf, msk)) 

6291 self.fill_value = flv 

6292 

6293 def __reduce__(self): 

6294 """Return a 3-tuple for pickling a MaskedArray. 

6295 

6296 """ 

6297 return (_mareconstruct, 

6298 (self.__class__, self._baseclass, (0,), 'b',), 

6299 self.__getstate__()) 

6300 

6301 def __deepcopy__(self, memo=None): 

6302 from copy import deepcopy 

6303 copied = MaskedArray.__new__(type(self), self, copy=True) 

6304 if memo is None: 

6305 memo = {} 

6306 memo[id(self)] = copied 

6307 for (k, v) in self.__dict__.items(): 

6308 copied.__dict__[k] = deepcopy(v, memo) 

6309 return copied 

6310 

6311 

6312def _mareconstruct(subtype, baseclass, baseshape, basetype,): 

6313 """Internal function that builds a new MaskedArray from the 

6314 information stored in a pickle. 

6315 

6316 """ 

6317 _data = ndarray.__new__(baseclass, baseshape, basetype) 

6318 _mask = ndarray.__new__(ndarray, baseshape, make_mask_descr(basetype)) 

6319 return subtype.__new__(subtype, _data, mask=_mask, dtype=basetype,) 

6320 

6321 

6322class mvoid(MaskedArray): 

6323 """ 

6324 Fake a 'void' object to use for masked array with structured dtypes. 

6325 """ 

6326 

6327 def __new__(self, data, mask=nomask, dtype=None, fill_value=None, 

6328 hardmask=False, copy=False, subok=True): 

6329 _data = np.array(data, copy=copy, subok=subok, dtype=dtype) 

6330 _data = _data.view(self) 

6331 _data._hardmask = hardmask 

6332 if mask is not nomask: 

6333 if isinstance(mask, np.void): 

6334 _data._mask = mask 

6335 else: 

6336 try: 

6337 # Mask is already a 0D array 

6338 _data._mask = np.void(mask) 

6339 except TypeError: 

6340 # Transform the mask to a void 

6341 mdtype = make_mask_descr(dtype) 

6342 _data._mask = np.array(mask, dtype=mdtype)[()] 

6343 if fill_value is not None: 

6344 _data.fill_value = fill_value 

6345 return _data 

6346 

6347 @property 

6348 def _data(self): 

6349 # Make sure that the _data part is a np.void 

6350 return super()._data[()] 

6351 

6352 def __getitem__(self, indx): 

6353 """ 

6354 Get the index. 

6355 

6356 """ 

6357 m = self._mask 

6358 if isinstance(m[indx], ndarray): 

6359 # Can happen when indx is a multi-dimensional field: 

6360 # A = ma.masked_array(data=[([0,1],)], mask=[([True, 

6361 # False],)], dtype=[("A", ">i2", (2,))]) 

6362 # x = A[0]; y = x["A"]; then y.mask["A"].size==2 

6363 # and we can not say masked/unmasked. 

6364 # The result is no longer mvoid! 

6365 # See also issue #6724. 

6366 return masked_array( 

6367 data=self._data[indx], mask=m[indx], 

6368 fill_value=self._fill_value[indx], 

6369 hard_mask=self._hardmask) 

6370 if m is not nomask and m[indx]: 

6371 return masked 

6372 return self._data[indx] 

6373 

6374 def __setitem__(self, indx, value): 

6375 self._data[indx] = value 

6376 if self._hardmask: 

6377 self._mask[indx] |= getattr(value, "_mask", False) 

6378 else: 

6379 self._mask[indx] = getattr(value, "_mask", False) 

6380 

6381 def __str__(self): 

6382 m = self._mask 

6383 if m is nomask: 

6384 return str(self._data) 

6385 

6386 rdtype = _replace_dtype_fields(self._data.dtype, "O") 

6387 data_arr = super()._data 

6388 res = data_arr.astype(rdtype) 

6389 _recursive_printoption(res, self._mask, masked_print_option) 

6390 return str(res) 

6391 

6392 __repr__ = __str__ 

6393 

6394 def __iter__(self): 

6395 "Defines an iterator for mvoid" 

6396 (_data, _mask) = (self._data, self._mask) 

6397 if _mask is nomask: 

6398 yield from _data 

6399 else: 

6400 for (d, m) in zip(_data, _mask): 

6401 if m: 

6402 yield masked 

6403 else: 

6404 yield d 

6405 

6406 def __len__(self): 

6407 return self._data.__len__() 

6408 

6409 def filled(self, fill_value=None): 

6410 """ 

6411 Return a copy with masked fields filled with a given value. 

6412 

6413 Parameters 

6414 ---------- 

6415 fill_value : array_like, optional 

6416 The value to use for invalid entries. Can be scalar or 

6417 non-scalar. If latter is the case, the filled array should 

6418 be broadcastable over input array. Default is None, in 

6419 which case the `fill_value` attribute is used instead. 

6420 

6421 Returns 

6422 ------- 

6423 filled_void 

6424 A `np.void` object 

6425 

6426 See Also 

6427 -------- 

6428 MaskedArray.filled 

6429 

6430 """ 

6431 return asarray(self).filled(fill_value)[()] 

6432 

6433 def tolist(self): 

6434 """ 

6435 Transforms the mvoid object into a tuple. 

6436 

6437 Masked fields are replaced by None. 

6438 

6439 Returns 

6440 ------- 

6441 returned_tuple 

6442 Tuple of fields 

6443 """ 

6444 _mask = self._mask 

6445 if _mask is nomask: 

6446 return self._data.tolist() 

6447 result = [] 

6448 for (d, m) in zip(self._data, self._mask): 

6449 if m: 

6450 result.append(None) 

6451 else: 

6452 # .item() makes sure we return a standard Python object 

6453 result.append(d.item()) 

6454 return tuple(result) 

6455 

6456 

6457############################################################################## 

6458# Shortcuts # 

6459############################################################################## 

6460 

6461 

6462def isMaskedArray(x): 

6463 """ 

6464 Test whether input is an instance of MaskedArray. 

6465 

6466 This function returns True if `x` is an instance of MaskedArray 

6467 and returns False otherwise. Any object is accepted as input. 

6468 

6469 Parameters 

6470 ---------- 

6471 x : object 

6472 Object to test. 

6473 

6474 Returns 

6475 ------- 

6476 result : bool 

6477 True if `x` is a MaskedArray. 

6478 

6479 See Also 

6480 -------- 

6481 isMA : Alias to isMaskedArray. 

6482 isarray : Alias to isMaskedArray. 

6483 

6484 Examples 

6485 -------- 

6486 >>> import numpy.ma as ma 

6487 >>> a = np.eye(3, 3) 

6488 >>> a 

6489 array([[ 1., 0., 0.], 

6490 [ 0., 1., 0.], 

6491 [ 0., 0., 1.]]) 

6492 >>> m = ma.masked_values(a, 0) 

6493 >>> m 

6494 masked_array( 

6495 data=[[1.0, --, --], 

6496 [--, 1.0, --], 

6497 [--, --, 1.0]], 

6498 mask=[[False, True, True], 

6499 [ True, False, True], 

6500 [ True, True, False]], 

6501 fill_value=0.0) 

6502 >>> ma.isMaskedArray(a) 

6503 False 

6504 >>> ma.isMaskedArray(m) 

6505 True 

6506 >>> ma.isMaskedArray([0, 1, 2]) 

6507 False 

6508 

6509 """ 

6510 return isinstance(x, MaskedArray) 

6511 

6512 

6513isarray = isMaskedArray 

6514isMA = isMaskedArray # backward compatibility 

6515 

6516 

6517class MaskedConstant(MaskedArray): 

6518 # the lone np.ma.masked instance 

6519 __singleton = None 

6520 

6521 @classmethod 

6522 def __has_singleton(cls): 

6523 # second case ensures `cls.__singleton` is not just a view on the 

6524 # superclass singleton 

6525 return cls.__singleton is not None and type(cls.__singleton) is cls 

6526 

6527 def __new__(cls): 

6528 if not cls.__has_singleton(): 

6529 # We define the masked singleton as a float for higher precedence. 

6530 # Note that it can be tricky sometimes w/ type comparison 

6531 data = np.array(0.) 

6532 mask = np.array(True) 

6533 

6534 # prevent any modifications 

6535 data.flags.writeable = False 

6536 mask.flags.writeable = False 

6537 

6538 # don't fall back on MaskedArray.__new__(MaskedConstant), since 

6539 # that might confuse it - this way, the construction is entirely 

6540 # within our control 

6541 cls.__singleton = MaskedArray(data, mask=mask).view(cls) 

6542 

6543 return cls.__singleton 

6544 

6545 def __array_finalize__(self, obj): 

6546 if not self.__has_singleton(): 

6547 # this handles the `.view` in __new__, which we want to copy across 

6548 # properties normally 

6549 return super().__array_finalize__(obj) 

6550 elif self is self.__singleton: 

6551 # not clear how this can happen, play it safe 

6552 pass 

6553 else: 

6554 # everywhere else, we want to downcast to MaskedArray, to prevent a 

6555 # duplicate maskedconstant. 

6556 self.__class__ = MaskedArray 

6557 MaskedArray.__array_finalize__(self, obj) 

6558 

6559 def __array_prepare__(self, obj, context=None): 

6560 return self.view(MaskedArray).__array_prepare__(obj, context) 

6561 

6562 def __array_wrap__(self, obj, context=None): 

6563 return self.view(MaskedArray).__array_wrap__(obj, context) 

6564 

6565 def __str__(self): 

6566 return str(masked_print_option._display) 

6567 

6568 def __repr__(self): 

6569 if self is MaskedConstant.__singleton: 

6570 return 'masked' 

6571 else: 

6572 # it's a subclass, or something is wrong, make it obvious 

6573 return object.__repr__(self) 

6574 

6575 def __format__(self, format_spec): 

6576 # Replace ndarray.__format__ with the default, which supports no format characters. 

6577 # Supporting format characters is unwise here, because we do not know what type 

6578 # the user was expecting - better to not guess. 

6579 try: 

6580 return object.__format__(self, format_spec) 

6581 except TypeError: 

6582 # 2020-03-23, NumPy 1.19.0 

6583 warnings.warn( 

6584 "Format strings passed to MaskedConstant are ignored, but in future may " 

6585 "error or produce different behavior", 

6586 FutureWarning, stacklevel=2 

6587 ) 

6588 return object.__format__(self, "") 

6589 

6590 def __reduce__(self): 

6591 """Override of MaskedArray's __reduce__. 

6592 """ 

6593 return (self.__class__, ()) 

6594 

6595 # inplace operations have no effect. We have to override them to avoid 

6596 # trying to modify the readonly data and mask arrays 

6597 def __iop__(self, other): 

6598 return self 

6599 __iadd__ = \ 

6600 __isub__ = \ 

6601 __imul__ = \ 

6602 __ifloordiv__ = \ 

6603 __itruediv__ = \ 

6604 __ipow__ = \ 

6605 __iop__ 

6606 del __iop__ # don't leave this around 

6607 

6608 def copy(self, *args, **kwargs): 

6609 """ Copy is a no-op on the maskedconstant, as it is a scalar """ 

6610 # maskedconstant is a scalar, so copy doesn't need to copy. There's 

6611 # precedent for this with `np.bool_` scalars. 

6612 return self 

6613 

6614 def __copy__(self): 

6615 return self 

6616 

6617 def __deepcopy__(self, memo): 

6618 return self 

6619 

6620 def __setattr__(self, attr, value): 

6621 if not self.__has_singleton(): 

6622 # allow the singleton to be initialized 

6623 return super().__setattr__(attr, value) 

6624 elif self is self.__singleton: 

6625 raise AttributeError( 

6626 f"attributes of {self!r} are not writeable") 

6627 else: 

6628 # duplicate instance - we can end up here from __array_finalize__, 

6629 # where we set the __class__ attribute 

6630 return super().__setattr__(attr, value) 

6631 

6632 

6633masked = masked_singleton = MaskedConstant() 

6634masked_array = MaskedArray 

6635 

6636 

6637def array(data, dtype=None, copy=False, order=None, 

6638 mask=nomask, fill_value=None, keep_mask=True, 

6639 hard_mask=False, shrink=True, subok=True, ndmin=0): 

6640 """ 

6641 Shortcut to MaskedArray. 

6642 

6643 The options are in a different order for convenience and backwards 

6644 compatibility. 

6645 

6646 """ 

6647 return MaskedArray(data, mask=mask, dtype=dtype, copy=copy, 

6648 subok=subok, keep_mask=keep_mask, 

6649 hard_mask=hard_mask, fill_value=fill_value, 

6650 ndmin=ndmin, shrink=shrink, order=order) 

6651array.__doc__ = masked_array.__doc__ 

6652 

6653 

6654def is_masked(x): 

6655 """ 

6656 Determine whether input has masked values. 

6657 

6658 Accepts any object as input, but always returns False unless the 

6659 input is a MaskedArray containing masked values. 

6660 

6661 Parameters 

6662 ---------- 

6663 x : array_like 

6664 Array to check for masked values. 

6665 

6666 Returns 

6667 ------- 

6668 result : bool 

6669 True if `x` is a MaskedArray with masked values, False otherwise. 

6670 

6671 Examples 

6672 -------- 

6673 >>> import numpy.ma as ma 

6674 >>> x = ma.masked_equal([0, 1, 0, 2, 3], 0) 

6675 >>> x 

6676 masked_array(data=[--, 1, --, 2, 3], 

6677 mask=[ True, False, True, False, False], 

6678 fill_value=0) 

6679 >>> ma.is_masked(x) 

6680 True 

6681 >>> x = ma.masked_equal([0, 1, 0, 2, 3], 42) 

6682 >>> x 

6683 masked_array(data=[0, 1, 0, 2, 3], 

6684 mask=False, 

6685 fill_value=42) 

6686 >>> ma.is_masked(x) 

6687 False 

6688 

6689 Always returns False if `x` isn't a MaskedArray. 

6690 

6691 >>> x = [False, True, False] 

6692 >>> ma.is_masked(x) 

6693 False 

6694 >>> x = 'a string' 

6695 >>> ma.is_masked(x) 

6696 False 

6697 

6698 """ 

6699 m = getmask(x) 

6700 if m is nomask: 

6701 return False 

6702 elif m.any(): 

6703 return True 

6704 return False 

6705 

6706 

6707############################################################################## 

6708# Extrema functions # 

6709############################################################################## 

6710 

6711 

6712class _extrema_operation(_MaskedUFunc): 

6713 """ 

6714 Generic class for maximum/minimum functions. 

6715 

6716 .. note:: 

6717 This is the base class for `_maximum_operation` and 

6718 `_minimum_operation`. 

6719 

6720 """ 

6721 def __init__(self, ufunc, compare, fill_value): 

6722 super().__init__(ufunc) 

6723 self.compare = compare 

6724 self.fill_value_func = fill_value 

6725 

6726 def __call__(self, a, b): 

6727 "Executes the call behavior." 

6728 

6729 return where(self.compare(a, b), a, b) 

6730 

6731 def reduce(self, target, axis=np._NoValue): 

6732 "Reduce target along the given axis." 

6733 target = narray(target, copy=False, subok=True) 

6734 m = getmask(target) 

6735 

6736 if axis is np._NoValue and target.ndim > 1: 

6737 # 2017-05-06, Numpy 1.13.0: warn on axis default 

6738 warnings.warn( 

6739 f"In the future the default for ma.{self.__name__}.reduce will be axis=0, " 

6740 f"not the current None, to match np.{self.__name__}.reduce. " 

6741 "Explicitly pass 0 or None to silence this warning.", 

6742 MaskedArrayFutureWarning, stacklevel=2) 

6743 axis = None 

6744 

6745 if axis is not np._NoValue: 

6746 kwargs = dict(axis=axis) 

6747 else: 

6748 kwargs = dict() 

6749 

6750 if m is nomask: 

6751 t = self.f.reduce(target, **kwargs) 

6752 else: 

6753 target = target.filled( 

6754 self.fill_value_func(target)).view(type(target)) 

6755 t = self.f.reduce(target, **kwargs) 

6756 m = umath.logical_and.reduce(m, **kwargs) 

6757 if hasattr(t, '_mask'): 

6758 t._mask = m 

6759 elif m: 

6760 t = masked 

6761 return t 

6762 

6763 def outer(self, a, b): 

6764 "Return the function applied to the outer product of a and b." 

6765 ma = getmask(a) 

6766 mb = getmask(b) 

6767 if ma is nomask and mb is nomask: 

6768 m = nomask 

6769 else: 

6770 ma = getmaskarray(a) 

6771 mb = getmaskarray(b) 

6772 m = logical_or.outer(ma, mb) 

6773 result = self.f.outer(filled(a), filled(b)) 

6774 if not isinstance(result, MaskedArray): 

6775 result = result.view(MaskedArray) 

6776 result._mask = m 

6777 return result 

6778 

6779def min(obj, axis=None, out=None, fill_value=None, keepdims=np._NoValue): 

6780 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

6781 

6782 try: 

6783 return obj.min(axis=axis, fill_value=fill_value, out=out, **kwargs) 

6784 except (AttributeError, TypeError): 

6785 # If obj doesn't have a min method, or if the method doesn't accept a 

6786 # fill_value argument 

6787 return asanyarray(obj).min(axis=axis, fill_value=fill_value, 

6788 out=out, **kwargs) 

6789min.__doc__ = MaskedArray.min.__doc__ 

6790 

6791def max(obj, axis=None, out=None, fill_value=None, keepdims=np._NoValue): 

6792 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

6793 

6794 try: 

6795 return obj.max(axis=axis, fill_value=fill_value, out=out, **kwargs) 

6796 except (AttributeError, TypeError): 

6797 # If obj doesn't have a max method, or if the method doesn't accept a 

6798 # fill_value argument 

6799 return asanyarray(obj).max(axis=axis, fill_value=fill_value, 

6800 out=out, **kwargs) 

6801max.__doc__ = MaskedArray.max.__doc__ 

6802 

6803 

6804def ptp(obj, axis=None, out=None, fill_value=None, keepdims=np._NoValue): 

6805 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

6806 try: 

6807 return obj.ptp(axis, out=out, fill_value=fill_value, **kwargs) 

6808 except (AttributeError, TypeError): 

6809 # If obj doesn't have a ptp method or if the method doesn't accept 

6810 # a fill_value argument 

6811 return asanyarray(obj).ptp(axis=axis, fill_value=fill_value, 

6812 out=out, **kwargs) 

6813ptp.__doc__ = MaskedArray.ptp.__doc__ 

6814 

6815 

6816############################################################################## 

6817# Definition of functions from the corresponding methods # 

6818############################################################################## 

6819 

6820 

6821class _frommethod: 

6822 """ 

6823 Define functions from existing MaskedArray methods. 

6824 

6825 Parameters 

6826 ---------- 

6827 methodname : str 

6828 Name of the method to transform. 

6829 

6830 """ 

6831 

6832 def __init__(self, methodname, reversed=False): 

6833 self.__name__ = methodname 

6834 self.__doc__ = self.getdoc() 

6835 self.reversed = reversed 

6836 

6837 def getdoc(self): 

6838 "Return the doc of the function (from the doc of the method)." 

6839 meth = getattr(MaskedArray, self.__name__, None) or\ 

6840 getattr(np, self.__name__, None) 

6841 signature = self.__name__ + get_object_signature(meth) 

6842 if meth is not None: 

6843 doc = """ %s\n%s""" % ( 

6844 signature, getattr(meth, '__doc__', None)) 

6845 return doc 

6846 

6847 def __call__(self, a, *args, **params): 

6848 if self.reversed: 

6849 args = list(args) 

6850 a, args[0] = args[0], a 

6851 

6852 marr = asanyarray(a) 

6853 method_name = self.__name__ 

6854 method = getattr(type(marr), method_name, None) 

6855 if method is None: 

6856 # use the corresponding np function 

6857 method = getattr(np, method_name) 

6858 

6859 return method(marr, *args, **params) 

6860 

6861 

6862all = _frommethod('all') 

6863anomalies = anom = _frommethod('anom') 

6864any = _frommethod('any') 

6865compress = _frommethod('compress', reversed=True) 

6866cumprod = _frommethod('cumprod') 

6867cumsum = _frommethod('cumsum') 

6868copy = _frommethod('copy') 

6869diagonal = _frommethod('diagonal') 

6870harden_mask = _frommethod('harden_mask') 

6871ids = _frommethod('ids') 

6872maximum = _extrema_operation(umath.maximum, greater, maximum_fill_value) 

6873mean = _frommethod('mean') 

6874minimum = _extrema_operation(umath.minimum, less, minimum_fill_value) 

6875nonzero = _frommethod('nonzero') 

6876prod = _frommethod('prod') 

6877product = _frommethod('prod') 

6878ravel = _frommethod('ravel') 

6879repeat = _frommethod('repeat') 

6880shrink_mask = _frommethod('shrink_mask') 

6881soften_mask = _frommethod('soften_mask') 

6882std = _frommethod('std') 

6883sum = _frommethod('sum') 

6884swapaxes = _frommethod('swapaxes') 

6885#take = _frommethod('take') 

6886trace = _frommethod('trace') 

6887var = _frommethod('var') 

6888 

6889count = _frommethod('count') 

6890 

6891def take(a, indices, axis=None, out=None, mode='raise'): 

6892 """ 

6893 """ 

6894 a = masked_array(a) 

6895 return a.take(indices, axis=axis, out=out, mode=mode) 

6896 

6897 

6898def power(a, b, third=None): 

6899 """ 

6900 Returns element-wise base array raised to power from second array. 

6901 

6902 This is the masked array version of `numpy.power`. For details see 

6903 `numpy.power`. 

6904 

6905 See Also 

6906 -------- 

6907 numpy.power 

6908 

6909 Notes 

6910 ----- 

6911 The *out* argument to `numpy.power` is not supported, `third` has to be 

6912 None. 

6913 

6914 Examples 

6915 -------- 

6916 >>> import numpy.ma as ma 

6917 >>> x = [11.2, -3.973, 0.801, -1.41] 

6918 >>> mask = [0, 0, 0, 1] 

6919 >>> masked_x = ma.masked_array(x, mask) 

6920 >>> masked_x 

6921 masked_array(data=[11.2, -3.973, 0.801, --], 

6922 mask=[False, False, False, True], 

6923 fill_value=1e+20) 

6924 >>> ma.power(masked_x, 2) 

6925 masked_array(data=[125.43999999999998, 15.784728999999999, 

6926 0.6416010000000001, --], 

6927 mask=[False, False, False, True], 

6928 fill_value=1e+20) 

6929 >>> y = [-0.5, 2, 0, 17] 

6930 >>> masked_y = ma.masked_array(y, mask) 

6931 >>> masked_y 

6932 masked_array(data=[-0.5, 2.0, 0.0, --], 

6933 mask=[False, False, False, True], 

6934 fill_value=1e+20) 

6935 >>> ma.power(masked_x, masked_y) 

6936 masked_array(data=[0.29880715233359845, 15.784728999999999, 1.0, --], 

6937 mask=[False, False, False, True], 

6938 fill_value=1e+20) 

6939 

6940 """ 

6941 if third is not None: 

6942 raise MaskError("3-argument power not supported.") 

6943 # Get the masks 

6944 ma = getmask(a) 

6945 mb = getmask(b) 

6946 m = mask_or(ma, mb) 

6947 # Get the rawdata 

6948 fa = getdata(a) 

6949 fb = getdata(b) 

6950 # Get the type of the result (so that we preserve subclasses) 

6951 if isinstance(a, MaskedArray): 

6952 basetype = type(a) 

6953 else: 

6954 basetype = MaskedArray 

6955 # Get the result and view it as a (subclass of) MaskedArray 

6956 with np.errstate(divide='ignore', invalid='ignore'): 

6957 result = np.where(m, fa, umath.power(fa, fb)).view(basetype) 

6958 result._update_from(a) 

6959 # Find where we're in trouble w/ NaNs and Infs 

6960 invalid = np.logical_not(np.isfinite(result.view(ndarray))) 

6961 # Add the initial mask 

6962 if m is not nomask: 

6963 if not result.ndim: 

6964 return masked 

6965 result._mask = np.logical_or(m, invalid) 

6966 # Fix the invalid parts 

6967 if invalid.any(): 

6968 if not result.ndim: 

6969 return masked 

6970 elif result._mask is nomask: 

6971 result._mask = invalid 

6972 result._data[invalid] = result.fill_value 

6973 return result 

6974 

6975argmin = _frommethod('argmin') 

6976argmax = _frommethod('argmax') 

6977 

6978def argsort(a, axis=np._NoValue, kind=None, order=None, endwith=True, fill_value=None): 

6979 "Function version of the eponymous method." 

6980 a = np.asanyarray(a) 

6981 

6982 # 2017-04-11, Numpy 1.13.0, gh-8701: warn on axis default 

6983 if axis is np._NoValue: 

6984 axis = _deprecate_argsort_axis(a) 

6985 

6986 if isinstance(a, MaskedArray): 

6987 return a.argsort(axis=axis, kind=kind, order=order, 

6988 endwith=endwith, fill_value=fill_value) 

6989 else: 

6990 return a.argsort(axis=axis, kind=kind, order=order) 

6991argsort.__doc__ = MaskedArray.argsort.__doc__ 

6992 

6993def sort(a, axis=-1, kind=None, order=None, endwith=True, fill_value=None): 

6994 """ 

6995 Return a sorted copy of the masked array. 

6996 

6997 Equivalent to creating a copy of the array 

6998 and applying the MaskedArray ``sort()`` method. 

6999 

7000 Refer to ``MaskedArray.sort`` for the full documentation 

7001 

7002 See Also 

7003 -------- 

7004 MaskedArray.sort : equivalent method 

7005 """ 

7006 a = np.array(a, copy=True, subok=True) 

7007 if axis is None: 

7008 a = a.flatten() 

7009 axis = 0 

7010 

7011 if isinstance(a, MaskedArray): 

7012 a.sort(axis=axis, kind=kind, order=order, 

7013 endwith=endwith, fill_value=fill_value) 

7014 else: 

7015 a.sort(axis=axis, kind=kind, order=order) 

7016 return a 

7017 

7018 

7019def compressed(x): 

7020 """ 

7021 Return all the non-masked data as a 1-D array. 

7022 

7023 This function is equivalent to calling the "compressed" method of a 

7024 `ma.MaskedArray`, see `ma.MaskedArray.compressed` for details. 

7025 

7026 See Also 

7027 -------- 

7028 ma.MaskedArray.compressed : Equivalent method. 

7029 

7030 """ 

7031 return asanyarray(x).compressed() 

7032 

7033 

7034def concatenate(arrays, axis=0): 

7035 """ 

7036 Concatenate a sequence of arrays along the given axis. 

7037 

7038 Parameters 

7039 ---------- 

7040 arrays : sequence of array_like 

7041 The arrays must have the same shape, except in the dimension 

7042 corresponding to `axis` (the first, by default). 

7043 axis : int, optional 

7044 The axis along which the arrays will be joined. Default is 0. 

7045 

7046 Returns 

7047 ------- 

7048 result : MaskedArray 

7049 The concatenated array with any masked entries preserved. 

7050 

7051 See Also 

7052 -------- 

7053 numpy.concatenate : Equivalent function in the top-level NumPy module. 

7054 

7055 Examples 

7056 -------- 

7057 >>> import numpy.ma as ma 

7058 >>> a = ma.arange(3) 

7059 >>> a[1] = ma.masked 

7060 >>> b = ma.arange(2, 5) 

7061 >>> a 

7062 masked_array(data=[0, --, 2], 

7063 mask=[False, True, False], 

7064 fill_value=999999) 

7065 >>> b 

7066 masked_array(data=[2, 3, 4], 

7067 mask=False, 

7068 fill_value=999999) 

7069 >>> ma.concatenate([a, b]) 

7070 masked_array(data=[0, --, 2, 2, 3, 4], 

7071 mask=[False, True, False, False, False, False], 

7072 fill_value=999999) 

7073 

7074 """ 

7075 d = np.concatenate([getdata(a) for a in arrays], axis) 

7076 rcls = get_masked_subclass(*arrays) 

7077 data = d.view(rcls) 

7078 # Check whether one of the arrays has a non-empty mask. 

7079 for x in arrays: 

7080 if getmask(x) is not nomask: 

7081 break 

7082 else: 

7083 return data 

7084 # OK, so we have to concatenate the masks 

7085 dm = np.concatenate([getmaskarray(a) for a in arrays], axis) 

7086 dm = dm.reshape(d.shape) 

7087 

7088 # If we decide to keep a '_shrinkmask' option, we want to check that 

7089 # all of them are True, and then check for dm.any() 

7090 data._mask = _shrink_mask(dm) 

7091 return data 

7092 

7093 

7094def diag(v, k=0): 

7095 """ 

7096 Extract a diagonal or construct a diagonal array. 

7097 

7098 This function is the equivalent of `numpy.diag` that takes masked 

7099 values into account, see `numpy.diag` for details. 

7100 

7101 See Also 

7102 -------- 

7103 numpy.diag : Equivalent function for ndarrays. 

7104 

7105 """ 

7106 output = np.diag(v, k).view(MaskedArray) 

7107 if getmask(v) is not nomask: 

7108 output._mask = np.diag(v._mask, k) 

7109 return output 

7110 

7111 

7112def left_shift(a, n): 

7113 """ 

7114 Shift the bits of an integer to the left. 

7115 

7116 This is the masked array version of `numpy.left_shift`, for details 

7117 see that function. 

7118 

7119 See Also 

7120 -------- 

7121 numpy.left_shift 

7122 

7123 """ 

7124 m = getmask(a) 

7125 if m is nomask: 

7126 d = umath.left_shift(filled(a), n) 

7127 return masked_array(d) 

7128 else: 

7129 d = umath.left_shift(filled(a, 0), n) 

7130 return masked_array(d, mask=m) 

7131 

7132 

7133def right_shift(a, n): 

7134 """ 

7135 Shift the bits of an integer to the right. 

7136 

7137 This is the masked array version of `numpy.right_shift`, for details 

7138 see that function. 

7139 

7140 See Also 

7141 -------- 

7142 numpy.right_shift 

7143 

7144 """ 

7145 m = getmask(a) 

7146 if m is nomask: 

7147 d = umath.right_shift(filled(a), n) 

7148 return masked_array(d) 

7149 else: 

7150 d = umath.right_shift(filled(a, 0), n) 

7151 return masked_array(d, mask=m) 

7152 

7153 

7154def put(a, indices, values, mode='raise'): 

7155 """ 

7156 Set storage-indexed locations to corresponding values. 

7157 

7158 This function is equivalent to `MaskedArray.put`, see that method 

7159 for details. 

7160 

7161 See Also 

7162 -------- 

7163 MaskedArray.put 

7164 

7165 """ 

7166 # We can't use 'frommethod', the order of arguments is different 

7167 try: 

7168 return a.put(indices, values, mode=mode) 

7169 except AttributeError: 

7170 return narray(a, copy=False).put(indices, values, mode=mode) 

7171 

7172 

7173def putmask(a, mask, values): # , mode='raise'): 

7174 """ 

7175 Changes elements of an array based on conditional and input values. 

7176 

7177 This is the masked array version of `numpy.putmask`, for details see 

7178 `numpy.putmask`. 

7179 

7180 See Also 

7181 -------- 

7182 numpy.putmask 

7183 

7184 Notes 

7185 ----- 

7186 Using a masked array as `values` will **not** transform a `ndarray` into 

7187 a `MaskedArray`. 

7188 

7189 """ 

7190 # We can't use 'frommethod', the order of arguments is different 

7191 if not isinstance(a, MaskedArray): 

7192 a = a.view(MaskedArray) 

7193 (valdata, valmask) = (getdata(values), getmask(values)) 

7194 if getmask(a) is nomask: 

7195 if valmask is not nomask: 

7196 a._sharedmask = True 

7197 a._mask = make_mask_none(a.shape, a.dtype) 

7198 np.copyto(a._mask, valmask, where=mask) 

7199 elif a._hardmask: 

7200 if valmask is not nomask: 

7201 m = a._mask.copy() 

7202 np.copyto(m, valmask, where=mask) 

7203 a.mask |= m 

7204 else: 

7205 if valmask is nomask: 

7206 valmask = getmaskarray(values) 

7207 np.copyto(a._mask, valmask, where=mask) 

7208 np.copyto(a._data, valdata, where=mask) 

7209 return 

7210 

7211 

7212def transpose(a, axes=None): 

7213 """ 

7214 Permute the dimensions of an array. 

7215 

7216 This function is exactly equivalent to `numpy.transpose`. 

7217 

7218 See Also 

7219 -------- 

7220 numpy.transpose : Equivalent function in top-level NumPy module. 

7221 

7222 Examples 

7223 -------- 

7224 >>> import numpy.ma as ma 

7225 >>> x = ma.arange(4).reshape((2,2)) 

7226 >>> x[1, 1] = ma.masked 

7227 >>> x 

7228 masked_array( 

7229 data=[[0, 1], 

7230 [2, --]], 

7231 mask=[[False, False], 

7232 [False, True]], 

7233 fill_value=999999) 

7234 

7235 >>> ma.transpose(x) 

7236 masked_array( 

7237 data=[[0, 2], 

7238 [1, --]], 

7239 mask=[[False, False], 

7240 [False, True]], 

7241 fill_value=999999) 

7242 """ 

7243 # We can't use 'frommethod', as 'transpose' doesn't take keywords 

7244 try: 

7245 return a.transpose(axes) 

7246 except AttributeError: 

7247 return narray(a, copy=False).transpose(axes).view(MaskedArray) 

7248 

7249 

7250def reshape(a, new_shape, order='C'): 

7251 """ 

7252 Returns an array containing the same data with a new shape. 

7253 

7254 Refer to `MaskedArray.reshape` for full documentation. 

7255 

7256 See Also 

7257 -------- 

7258 MaskedArray.reshape : equivalent function 

7259 

7260 """ 

7261 # We can't use 'frommethod', it whine about some parameters. Dmmit. 

7262 try: 

7263 return a.reshape(new_shape, order=order) 

7264 except AttributeError: 

7265 _tmp = narray(a, copy=False).reshape(new_shape, order=order) 

7266 return _tmp.view(MaskedArray) 

7267 

7268 

7269def resize(x, new_shape): 

7270 """ 

7271 Return a new masked array with the specified size and shape. 

7272 

7273 This is the masked equivalent of the `numpy.resize` function. The new 

7274 array is filled with repeated copies of `x` (in the order that the 

7275 data are stored in memory). If `x` is masked, the new array will be 

7276 masked, and the new mask will be a repetition of the old one. 

7277 

7278 See Also 

7279 -------- 

7280 numpy.resize : Equivalent function in the top level NumPy module. 

7281 

7282 Examples 

7283 -------- 

7284 >>> import numpy.ma as ma 

7285 >>> a = ma.array([[1, 2] ,[3, 4]]) 

7286 >>> a[0, 1] = ma.masked 

7287 >>> a 

7288 masked_array( 

7289 data=[[1, --], 

7290 [3, 4]], 

7291 mask=[[False, True], 

7292 [False, False]], 

7293 fill_value=999999) 

7294 >>> np.resize(a, (3, 3)) 

7295 masked_array( 

7296 data=[[1, 2, 3], 

7297 [4, 1, 2], 

7298 [3, 4, 1]], 

7299 mask=False, 

7300 fill_value=999999) 

7301 >>> ma.resize(a, (3, 3)) 

7302 masked_array( 

7303 data=[[1, --, 3], 

7304 [4, 1, --], 

7305 [3, 4, 1]], 

7306 mask=[[False, True, False], 

7307 [False, False, True], 

7308 [False, False, False]], 

7309 fill_value=999999) 

7310 

7311 A MaskedArray is always returned, regardless of the input type. 

7312 

7313 >>> a = np.array([[1, 2] ,[3, 4]]) 

7314 >>> ma.resize(a, (3, 3)) 

7315 masked_array( 

7316 data=[[1, 2, 3], 

7317 [4, 1, 2], 

7318 [3, 4, 1]], 

7319 mask=False, 

7320 fill_value=999999) 

7321 

7322 """ 

7323 # We can't use _frommethods here, as N.resize is notoriously whiny. 

7324 m = getmask(x) 

7325 if m is not nomask: 

7326 m = np.resize(m, new_shape) 

7327 result = np.resize(x, new_shape).view(get_masked_subclass(x)) 

7328 if result.ndim: 

7329 result._mask = m 

7330 return result 

7331 

7332 

7333def ndim(obj): 

7334 """ 

7335 maskedarray version of the numpy function. 

7336 

7337 """ 

7338 return np.ndim(getdata(obj)) 

7339 

7340ndim.__doc__ = np.ndim.__doc__ 

7341 

7342 

7343def shape(obj): 

7344 "maskedarray version of the numpy function." 

7345 return np.shape(getdata(obj)) 

7346shape.__doc__ = np.shape.__doc__ 

7347 

7348 

7349def size(obj, axis=None): 

7350 "maskedarray version of the numpy function." 

7351 return np.size(getdata(obj), axis) 

7352size.__doc__ = np.size.__doc__ 

7353 

7354 

7355############################################################################## 

7356# Extra functions # 

7357############################################################################## 

7358 

7359 

7360def where(condition, x=_NoValue, y=_NoValue): 

7361 """ 

7362 Return a masked array with elements from `x` or `y`, depending on condition. 

7363 

7364 .. note:: 

7365 When only `condition` is provided, this function is identical to 

7366 `nonzero`. The rest of this documentation covers only the case where 

7367 all three arguments are provided. 

7368 

7369 Parameters 

7370 ---------- 

7371 condition : array_like, bool 

7372 Where True, yield `x`, otherwise yield `y`. 

7373 x, y : array_like, optional 

7374 Values from which to choose. `x`, `y` and `condition` need to be 

7375 broadcastable to some shape. 

7376 

7377 Returns 

7378 ------- 

7379 out : MaskedArray 

7380 An masked array with `masked` elements where the condition is masked, 

7381 elements from `x` where `condition` is True, and elements from `y` 

7382 elsewhere. 

7383 

7384 See Also 

7385 -------- 

7386 numpy.where : Equivalent function in the top-level NumPy module. 

7387 nonzero : The function that is called when x and y are omitted 

7388 

7389 Examples 

7390 -------- 

7391 >>> x = np.ma.array(np.arange(9.).reshape(3, 3), mask=[[0, 1, 0], 

7392 ... [1, 0, 1], 

7393 ... [0, 1, 0]]) 

7394 >>> x 

7395 masked_array( 

7396 data=[[0.0, --, 2.0], 

7397 [--, 4.0, --], 

7398 [6.0, --, 8.0]], 

7399 mask=[[False, True, False], 

7400 [ True, False, True], 

7401 [False, True, False]], 

7402 fill_value=1e+20) 

7403 >>> np.ma.where(x > 5, x, -3.1416) 

7404 masked_array( 

7405 data=[[-3.1416, --, -3.1416], 

7406 [--, -3.1416, --], 

7407 [6.0, --, 8.0]], 

7408 mask=[[False, True, False], 

7409 [ True, False, True], 

7410 [False, True, False]], 

7411 fill_value=1e+20) 

7412 

7413 """ 

7414 

7415 # handle the single-argument case 

7416 missing = (x is _NoValue, y is _NoValue).count(True) 

7417 if missing == 1: 

7418 raise ValueError("Must provide both 'x' and 'y' or neither.") 

7419 if missing == 2: 

7420 return nonzero(condition) 

7421 

7422 # we only care if the condition is true - false or masked pick y 

7423 cf = filled(condition, False) 

7424 xd = getdata(x) 

7425 yd = getdata(y) 

7426 

7427 # we need the full arrays here for correct final dimensions 

7428 cm = getmaskarray(condition) 

7429 xm = getmaskarray(x) 

7430 ym = getmaskarray(y) 

7431 

7432 # deal with the fact that masked.dtype == float64, but we don't actually 

7433 # want to treat it as that. 

7434 if x is masked and y is not masked: 

7435 xd = np.zeros((), dtype=yd.dtype) 

7436 xm = np.ones((), dtype=ym.dtype) 

7437 elif y is masked and x is not masked: 

7438 yd = np.zeros((), dtype=xd.dtype) 

7439 ym = np.ones((), dtype=xm.dtype) 

7440 

7441 data = np.where(cf, xd, yd) 

7442 mask = np.where(cf, xm, ym) 

7443 mask = np.where(cm, np.ones((), dtype=mask.dtype), mask) 

7444 

7445 # collapse the mask, for backwards compatibility 

7446 mask = _shrink_mask(mask) 

7447 

7448 return masked_array(data, mask=mask) 

7449 

7450 

7451def choose(indices, choices, out=None, mode='raise'): 

7452 """ 

7453 Use an index array to construct a new array from a list of choices. 

7454 

7455 Given an array of integers and a list of n choice arrays, this method 

7456 will create a new array that merges each of the choice arrays. Where a 

7457 value in `index` is i, the new array will have the value that choices[i] 

7458 contains in the same place. 

7459 

7460 Parameters 

7461 ---------- 

7462 indices : ndarray of ints 

7463 This array must contain integers in ``[0, n-1]``, where n is the 

7464 number of choices. 

7465 choices : sequence of arrays 

7466 Choice arrays. The index array and all of the choices should be 

7467 broadcastable to the same shape. 

7468 out : array, optional 

7469 If provided, the result will be inserted into this array. It should 

7470 be of the appropriate shape and `dtype`. 

7471 mode : {'raise', 'wrap', 'clip'}, optional 

7472 Specifies how out-of-bounds indices will behave. 

7473 

7474 * 'raise' : raise an error 

7475 * 'wrap' : wrap around 

7476 * 'clip' : clip to the range 

7477 

7478 Returns 

7479 ------- 

7480 merged_array : array 

7481 

7482 See Also 

7483 -------- 

7484 choose : equivalent function 

7485 

7486 Examples 

7487 -------- 

7488 >>> choice = np.array([[1,1,1], [2,2,2], [3,3,3]]) 

7489 >>> a = np.array([2, 1, 0]) 

7490 >>> np.ma.choose(a, choice) 

7491 masked_array(data=[3, 2, 1], 

7492 mask=False, 

7493 fill_value=999999) 

7494 

7495 """ 

7496 def fmask(x): 

7497 "Returns the filled array, or True if masked." 

7498 if x is masked: 

7499 return True 

7500 return filled(x) 

7501 

7502 def nmask(x): 

7503 "Returns the mask, True if ``masked``, False if ``nomask``." 

7504 if x is masked: 

7505 return True 

7506 return getmask(x) 

7507 # Get the indices. 

7508 c = filled(indices, 0) 

7509 # Get the masks. 

7510 masks = [nmask(x) for x in choices] 

7511 data = [fmask(x) for x in choices] 

7512 # Construct the mask 

7513 outputmask = np.choose(c, masks, mode=mode) 

7514 outputmask = make_mask(mask_or(outputmask, getmask(indices)), 

7515 copy=False, shrink=True) 

7516 # Get the choices. 

7517 d = np.choose(c, data, mode=mode, out=out).view(MaskedArray) 

7518 if out is not None: 

7519 if isinstance(out, MaskedArray): 

7520 out.__setmask__(outputmask) 

7521 return out 

7522 d.__setmask__(outputmask) 

7523 return d 

7524 

7525 

7526def round_(a, decimals=0, out=None): 

7527 """ 

7528 Return a copy of a, rounded to 'decimals' places. 

7529 

7530 When 'decimals' is negative, it specifies the number of positions 

7531 to the left of the decimal point. The real and imaginary parts of 

7532 complex numbers are rounded separately. Nothing is done if the 

7533 array is not of float type and 'decimals' is greater than or equal 

7534 to 0. 

7535 

7536 Parameters 

7537 ---------- 

7538 decimals : int 

7539 Number of decimals to round to. May be negative. 

7540 out : array_like 

7541 Existing array to use for output. 

7542 If not given, returns a default copy of a. 

7543 

7544 Notes 

7545 ----- 

7546 If out is given and does not have a mask attribute, the mask of a 

7547 is lost! 

7548 

7549 Examples 

7550 -------- 

7551 >>> import numpy.ma as ma 

7552 >>> x = [11.2, -3.973, 0.801, -1.41] 

7553 >>> mask = [0, 0, 0, 1] 

7554 >>> masked_x = ma.masked_array(x, mask) 

7555 >>> masked_x 

7556 masked_array(data=[11.2, -3.973, 0.801, --], 

7557 mask=[False, False, False, True], 

7558 fill_value=1e+20) 

7559 >>> ma.round_(masked_x) 

7560 masked_array(data=[11.0, -4.0, 1.0, --], 

7561 mask=[False, False, False, True], 

7562 fill_value=1e+20) 

7563 >>> ma.round(masked_x, decimals=1) 

7564 masked_array(data=[11.2, -4.0, 0.8, --], 

7565 mask=[False, False, False, True], 

7566 fill_value=1e+20) 

7567 >>> ma.round_(masked_x, decimals=-1) 

7568 masked_array(data=[10.0, -0.0, 0.0, --], 

7569 mask=[False, False, False, True], 

7570 fill_value=1e+20) 

7571 """ 

7572 if out is None: 

7573 return np.round_(a, decimals, out) 

7574 else: 

7575 np.round_(getdata(a), decimals, out) 

7576 if hasattr(out, '_mask'): 

7577 out._mask = getmask(a) 

7578 return out 

7579round = round_ 

7580 

7581 

7582# Needed by dot, so move here from extras.py. It will still be exported 

7583# from extras.py for compatibility. 

7584def mask_rowcols(a, axis=None): 

7585 """ 

7586 Mask rows and/or columns of a 2D array that contain masked values. 

7587 

7588 Mask whole rows and/or columns of a 2D array that contain 

7589 masked values. The masking behavior is selected using the 

7590 `axis` parameter. 

7591 

7592 - If `axis` is None, rows *and* columns are masked. 

7593 - If `axis` is 0, only rows are masked. 

7594 - If `axis` is 1 or -1, only columns are masked. 

7595 

7596 Parameters 

7597 ---------- 

7598 a : array_like, MaskedArray 

7599 The array to mask. If not a MaskedArray instance (or if no array 

7600 elements are masked). The result is a MaskedArray with `mask` set 

7601 to `nomask` (False). Must be a 2D array. 

7602 axis : int, optional 

7603 Axis along which to perform the operation. If None, applies to a 

7604 flattened version of the array. 

7605 

7606 Returns 

7607 ------- 

7608 a : MaskedArray 

7609 A modified version of the input array, masked depending on the value 

7610 of the `axis` parameter. 

7611 

7612 Raises 

7613 ------ 

7614 NotImplementedError 

7615 If input array `a` is not 2D. 

7616 

7617 See Also 

7618 -------- 

7619 mask_rows : Mask rows of a 2D array that contain masked values. 

7620 mask_cols : Mask cols of a 2D array that contain masked values. 

7621 masked_where : Mask where a condition is met. 

7622 

7623 Notes 

7624 ----- 

7625 The input array's mask is modified by this function. 

7626 

7627 Examples 

7628 -------- 

7629 >>> import numpy.ma as ma 

7630 >>> a = np.zeros((3, 3), dtype=int) 

7631 >>> a[1, 1] = 1 

7632 >>> a 

7633 array([[0, 0, 0], 

7634 [0, 1, 0], 

7635 [0, 0, 0]]) 

7636 >>> a = ma.masked_equal(a, 1) 

7637 >>> a 

7638 masked_array( 

7639 data=[[0, 0, 0], 

7640 [0, --, 0], 

7641 [0, 0, 0]], 

7642 mask=[[False, False, False], 

7643 [False, True, False], 

7644 [False, False, False]], 

7645 fill_value=1) 

7646 >>> ma.mask_rowcols(a) 

7647 masked_array( 

7648 data=[[0, --, 0], 

7649 [--, --, --], 

7650 [0, --, 0]], 

7651 mask=[[False, True, False], 

7652 [ True, True, True], 

7653 [False, True, False]], 

7654 fill_value=1) 

7655 

7656 """ 

7657 a = array(a, subok=False) 

7658 if a.ndim != 2: 

7659 raise NotImplementedError("mask_rowcols works for 2D arrays only.") 

7660 m = getmask(a) 

7661 # Nothing is masked: return a 

7662 if m is nomask or not m.any(): 

7663 return a 

7664 maskedval = m.nonzero() 

7665 a._mask = a._mask.copy() 

7666 if not axis: 

7667 a[np.unique(maskedval[0])] = masked 

7668 if axis in [None, 1, -1]: 

7669 a[:, np.unique(maskedval[1])] = masked 

7670 return a 

7671 

7672 

7673# Include masked dot here to avoid import problems in getting it from 

7674# extras.py. Note that it is not included in __all__, but rather exported 

7675# from extras in order to avoid backward compatibility problems. 

7676def dot(a, b, strict=False, out=None): 

7677 """ 

7678 Return the dot product of two arrays. 

7679 

7680 This function is the equivalent of `numpy.dot` that takes masked values 

7681 into account. Note that `strict` and `out` are in different position 

7682 than in the method version. In order to maintain compatibility with the 

7683 corresponding method, it is recommended that the optional arguments be 

7684 treated as keyword only. At some point that may be mandatory. 

7685 

7686 .. note:: 

7687 Works only with 2-D arrays at the moment. 

7688 

7689 

7690 Parameters 

7691 ---------- 

7692 a, b : masked_array_like 

7693 Inputs arrays. 

7694 strict : bool, optional 

7695 Whether masked data are propagated (True) or set to 0 (False) for 

7696 the computation. Default is False. Propagating the mask means that 

7697 if a masked value appears in a row or column, the whole row or 

7698 column is considered masked. 

7699 out : masked_array, optional 

7700 Output argument. This must have the exact kind that would be returned 

7701 if it was not used. In particular, it must have the right type, must be 

7702 C-contiguous, and its dtype must be the dtype that would be returned 

7703 for `dot(a,b)`. This is a performance feature. Therefore, if these 

7704 conditions are not met, an exception is raised, instead of attempting 

7705 to be flexible. 

7706 

7707 .. versionadded:: 1.10.2 

7708 

7709 See Also 

7710 -------- 

7711 numpy.dot : Equivalent function for ndarrays. 

7712 

7713 Examples 

7714 -------- 

7715 >>> a = np.ma.array([[1, 2, 3], [4, 5, 6]], mask=[[1, 0, 0], [0, 0, 0]]) 

7716 >>> b = np.ma.array([[1, 2], [3, 4], [5, 6]], mask=[[1, 0], [0, 0], [0, 0]]) 

7717 >>> np.ma.dot(a, b) 

7718 masked_array( 

7719 data=[[21, 26], 

7720 [45, 64]], 

7721 mask=[[False, False], 

7722 [False, False]], 

7723 fill_value=999999) 

7724 >>> np.ma.dot(a, b, strict=True) 

7725 masked_array( 

7726 data=[[--, --], 

7727 [--, 64]], 

7728 mask=[[ True, True], 

7729 [ True, False]], 

7730 fill_value=999999) 

7731 

7732 """ 

7733 # !!!: Works only with 2D arrays. There should be a way to get it to run 

7734 # with higher dimension 

7735 if strict and (a.ndim == 2) and (b.ndim == 2): 

7736 a = mask_rowcols(a, 0) 

7737 b = mask_rowcols(b, 1) 

7738 am = ~getmaskarray(a) 

7739 bm = ~getmaskarray(b) 

7740 

7741 if out is None: 

7742 d = np.dot(filled(a, 0), filled(b, 0)) 

7743 m = ~np.dot(am, bm) 

7744 if d.ndim == 0: 

7745 d = np.asarray(d) 

7746 r = d.view(get_masked_subclass(a, b)) 

7747 r.__setmask__(m) 

7748 return r 

7749 else: 

7750 d = np.dot(filled(a, 0), filled(b, 0), out._data) 

7751 if out.mask.shape != d.shape: 

7752 out._mask = np.empty(d.shape, MaskType) 

7753 np.dot(am, bm, out._mask) 

7754 np.logical_not(out._mask, out._mask) 

7755 return out 

7756 

7757 

7758def inner(a, b): 

7759 """ 

7760 Returns the inner product of a and b for arrays of floating point types. 

7761 

7762 Like the generic NumPy equivalent the product sum is over the last dimension 

7763 of a and b. The first argument is not conjugated. 

7764 

7765 """ 

7766 fa = filled(a, 0) 

7767 fb = filled(b, 0) 

7768 if fa.ndim == 0: 

7769 fa.shape = (1,) 

7770 if fb.ndim == 0: 

7771 fb.shape = (1,) 

7772 return np.inner(fa, fb).view(MaskedArray) 

7773inner.__doc__ = doc_note(np.inner.__doc__, 

7774 "Masked values are replaced by 0.") 

7775innerproduct = inner 

7776 

7777 

7778def outer(a, b): 

7779 "maskedarray version of the numpy function." 

7780 fa = filled(a, 0).ravel() 

7781 fb = filled(b, 0).ravel() 

7782 d = np.outer(fa, fb) 

7783 ma = getmask(a) 

7784 mb = getmask(b) 

7785 if ma is nomask and mb is nomask: 

7786 return masked_array(d) 

7787 ma = getmaskarray(a) 

7788 mb = getmaskarray(b) 

7789 m = make_mask(1 - np.outer(1 - ma, 1 - mb), copy=False) 

7790 return masked_array(d, mask=m) 

7791outer.__doc__ = doc_note(np.outer.__doc__, 

7792 "Masked values are replaced by 0.") 

7793outerproduct = outer 

7794 

7795 

7796def _convolve_or_correlate(f, a, v, mode, propagate_mask): 

7797 """ 

7798 Helper function for ma.correlate and ma.convolve 

7799 """ 

7800 if propagate_mask: 

7801 # results which are contributed to by either item in any pair being invalid 

7802 mask = ( 

7803 f(getmaskarray(a), np.ones(np.shape(v), dtype=bool), mode=mode) 

7804 | f(np.ones(np.shape(a), dtype=bool), getmaskarray(v), mode=mode) 

7805 ) 

7806 data = f(getdata(a), getdata(v), mode=mode) 

7807 else: 

7808 # results which are not contributed to by any pair of valid elements 

7809 mask = ~f(~getmaskarray(a), ~getmaskarray(v)) 

7810 data = f(filled(a, 0), filled(v, 0), mode=mode) 

7811 

7812 return masked_array(data, mask=mask) 

7813 

7814 

7815def correlate(a, v, mode='valid', propagate_mask=True): 

7816 """ 

7817 Cross-correlation of two 1-dimensional sequences. 

7818 

7819 Parameters 

7820 ---------- 

7821 a, v : array_like 

7822 Input sequences. 

7823 mode : {'valid', 'same', 'full'}, optional 

7824 Refer to the `np.convolve` docstring. Note that the default 

7825 is 'valid', unlike `convolve`, which uses 'full'. 

7826 propagate_mask : bool 

7827 If True, then a result element is masked if any masked element contributes towards it. 

7828 If False, then a result element is only masked if no non-masked element 

7829 contribute towards it 

7830 

7831 Returns 

7832 ------- 

7833 out : MaskedArray 

7834 Discrete cross-correlation of `a` and `v`. 

7835 

7836 See Also 

7837 -------- 

7838 numpy.correlate : Equivalent function in the top-level NumPy module. 

7839 """ 

7840 return _convolve_or_correlate(np.correlate, a, v, mode, propagate_mask) 

7841 

7842 

7843def convolve(a, v, mode='full', propagate_mask=True): 

7844 """ 

7845 Returns the discrete, linear convolution of two one-dimensional sequences. 

7846 

7847 Parameters 

7848 ---------- 

7849 a, v : array_like 

7850 Input sequences. 

7851 mode : {'valid', 'same', 'full'}, optional 

7852 Refer to the `np.convolve` docstring. 

7853 propagate_mask : bool 

7854 If True, then if any masked element is included in the sum for a result 

7855 element, then the result is masked. 

7856 If False, then the result element is only masked if no non-masked cells 

7857 contribute towards it 

7858 

7859 Returns 

7860 ------- 

7861 out : MaskedArray 

7862 Discrete, linear convolution of `a` and `v`. 

7863 

7864 See Also 

7865 -------- 

7866 numpy.convolve : Equivalent function in the top-level NumPy module. 

7867 """ 

7868 return _convolve_or_correlate(np.convolve, a, v, mode, propagate_mask) 

7869 

7870 

7871def allequal(a, b, fill_value=True): 

7872 """ 

7873 Return True if all entries of a and b are equal, using 

7874 fill_value as a truth value where either or both are masked. 

7875 

7876 Parameters 

7877 ---------- 

7878 a, b : array_like 

7879 Input arrays to compare. 

7880 fill_value : bool, optional 

7881 Whether masked values in a or b are considered equal (True) or not 

7882 (False). 

7883 

7884 Returns 

7885 ------- 

7886 y : bool 

7887 Returns True if the two arrays are equal within the given 

7888 tolerance, False otherwise. If either array contains NaN, 

7889 then False is returned. 

7890 

7891 See Also 

7892 -------- 

7893 all, any 

7894 numpy.ma.allclose 

7895 

7896 Examples 

7897 -------- 

7898 >>> a = np.ma.array([1e10, 1e-7, 42.0], mask=[0, 0, 1]) 

7899 >>> a 

7900 masked_array(data=[10000000000.0, 1e-07, --], 

7901 mask=[False, False, True], 

7902 fill_value=1e+20) 

7903 

7904 >>> b = np.array([1e10, 1e-7, -42.0]) 

7905 >>> b 

7906 array([ 1.00000000e+10, 1.00000000e-07, -4.20000000e+01]) 

7907 >>> np.ma.allequal(a, b, fill_value=False) 

7908 False 

7909 >>> np.ma.allequal(a, b) 

7910 True 

7911 

7912 """ 

7913 m = mask_or(getmask(a), getmask(b)) 

7914 if m is nomask: 

7915 x = getdata(a) 

7916 y = getdata(b) 

7917 d = umath.equal(x, y) 

7918 return d.all() 

7919 elif fill_value: 

7920 x = getdata(a) 

7921 y = getdata(b) 

7922 d = umath.equal(x, y) 

7923 dm = array(d, mask=m, copy=False) 

7924 return dm.filled(True).all(None) 

7925 else: 

7926 return False 

7927 

7928 

7929def allclose(a, b, masked_equal=True, rtol=1e-5, atol=1e-8): 

7930 """ 

7931 Returns True if two arrays are element-wise equal within a tolerance. 

7932 

7933 This function is equivalent to `allclose` except that masked values 

7934 are treated as equal (default) or unequal, depending on the `masked_equal` 

7935 argument. 

7936 

7937 Parameters 

7938 ---------- 

7939 a, b : array_like 

7940 Input arrays to compare. 

7941 masked_equal : bool, optional 

7942 Whether masked values in `a` and `b` are considered equal (True) or not 

7943 (False). They are considered equal by default. 

7944 rtol : float, optional 

7945 Relative tolerance. The relative difference is equal to ``rtol * b``. 

7946 Default is 1e-5. 

7947 atol : float, optional 

7948 Absolute tolerance. The absolute difference is equal to `atol`. 

7949 Default is 1e-8. 

7950 

7951 Returns 

7952 ------- 

7953 y : bool 

7954 Returns True if the two arrays are equal within the given 

7955 tolerance, False otherwise. If either array contains NaN, then 

7956 False is returned. 

7957 

7958 See Also 

7959 -------- 

7960 all, any 

7961 numpy.allclose : the non-masked `allclose`. 

7962 

7963 Notes 

7964 ----- 

7965 If the following equation is element-wise True, then `allclose` returns 

7966 True:: 

7967 

7968 absolute(`a` - `b`) <= (`atol` + `rtol` * absolute(`b`)) 

7969 

7970 Return True if all elements of `a` and `b` are equal subject to 

7971 given tolerances. 

7972 

7973 Examples 

7974 -------- 

7975 >>> a = np.ma.array([1e10, 1e-7, 42.0], mask=[0, 0, 1]) 

7976 >>> a 

7977 masked_array(data=[10000000000.0, 1e-07, --], 

7978 mask=[False, False, True], 

7979 fill_value=1e+20) 

7980 >>> b = np.ma.array([1e10, 1e-8, -42.0], mask=[0, 0, 1]) 

7981 >>> np.ma.allclose(a, b) 

7982 False 

7983 

7984 >>> a = np.ma.array([1e10, 1e-8, 42.0], mask=[0, 0, 1]) 

7985 >>> b = np.ma.array([1.00001e10, 1e-9, -42.0], mask=[0, 0, 1]) 

7986 >>> np.ma.allclose(a, b) 

7987 True 

7988 >>> np.ma.allclose(a, b, masked_equal=False) 

7989 False 

7990 

7991 Masked values are not compared directly. 

7992 

7993 >>> a = np.ma.array([1e10, 1e-8, 42.0], mask=[0, 0, 1]) 

7994 >>> b = np.ma.array([1.00001e10, 1e-9, 42.0], mask=[0, 0, 1]) 

7995 >>> np.ma.allclose(a, b) 

7996 True 

7997 >>> np.ma.allclose(a, b, masked_equal=False) 

7998 False 

7999 

8000 """ 

8001 x = masked_array(a, copy=False) 

8002 y = masked_array(b, copy=False) 

8003 

8004 # make sure y is an inexact type to avoid abs(MIN_INT); will cause 

8005 # casting of x later. 

8006 # NOTE: We explicitly allow timedelta, which used to work. This could 

8007 # possibly be deprecated. See also gh-18286. 

8008 # timedelta works if `atol` is an integer or also a timedelta. 

8009 # Although, the default tolerances are unlikely to be useful 

8010 if y.dtype.kind != "m": 

8011 dtype = np.result_type(y, 1.) 

8012 if y.dtype != dtype: 

8013 y = masked_array(y, dtype=dtype, copy=False) 

8014 

8015 m = mask_or(getmask(x), getmask(y)) 

8016 xinf = np.isinf(masked_array(x, copy=False, mask=m)).filled(False) 

8017 # If we have some infs, they should fall at the same place. 

8018 if not np.all(xinf == filled(np.isinf(y), False)): 

8019 return False 

8020 # No infs at all 

8021 if not np.any(xinf): 

8022 d = filled(less_equal(absolute(x - y), atol + rtol * absolute(y)), 

8023 masked_equal) 

8024 return np.all(d) 

8025 

8026 if not np.all(filled(x[xinf] == y[xinf], masked_equal)): 

8027 return False 

8028 x = x[~xinf] 

8029 y = y[~xinf] 

8030 

8031 d = filled(less_equal(absolute(x - y), atol + rtol * absolute(y)), 

8032 masked_equal) 

8033 

8034 return np.all(d) 

8035 

8036 

8037def asarray(a, dtype=None, order=None): 

8038 """ 

8039 Convert the input to a masked array of the given data-type. 

8040 

8041 No copy is performed if the input is already an `ndarray`. If `a` is 

8042 a subclass of `MaskedArray`, a base class `MaskedArray` is returned. 

8043 

8044 Parameters 

8045 ---------- 

8046 a : array_like 

8047 Input data, in any form that can be converted to a masked array. This 

8048 includes lists, lists of tuples, tuples, tuples of tuples, tuples 

8049 of lists, ndarrays and masked arrays. 

8050 dtype : dtype, optional 

8051 By default, the data-type is inferred from the input data. 

8052 order : {'C', 'F'}, optional 

8053 Whether to use row-major ('C') or column-major ('FORTRAN') memory 

8054 representation. Default is 'C'. 

8055 

8056 Returns 

8057 ------- 

8058 out : MaskedArray 

8059 Masked array interpretation of `a`. 

8060 

8061 See Also 

8062 -------- 

8063 asanyarray : Similar to `asarray`, but conserves subclasses. 

8064 

8065 Examples 

8066 -------- 

8067 >>> x = np.arange(10.).reshape(2, 5) 

8068 >>> x 

8069 array([[0., 1., 2., 3., 4.], 

8070 [5., 6., 7., 8., 9.]]) 

8071 >>> np.ma.asarray(x) 

8072 masked_array( 

8073 data=[[0., 1., 2., 3., 4.], 

8074 [5., 6., 7., 8., 9.]], 

8075 mask=False, 

8076 fill_value=1e+20) 

8077 >>> type(np.ma.asarray(x)) 

8078 <class 'numpy.ma.core.MaskedArray'> 

8079 

8080 """ 

8081 order = order or 'C' 

8082 return masked_array(a, dtype=dtype, copy=False, keep_mask=True, 

8083 subok=False, order=order) 

8084 

8085 

8086def asanyarray(a, dtype=None): 

8087 """ 

8088 Convert the input to a masked array, conserving subclasses. 

8089 

8090 If `a` is a subclass of `MaskedArray`, its class is conserved. 

8091 No copy is performed if the input is already an `ndarray`. 

8092 

8093 Parameters 

8094 ---------- 

8095 a : array_like 

8096 Input data, in any form that can be converted to an array. 

8097 dtype : dtype, optional 

8098 By default, the data-type is inferred from the input data. 

8099 order : {'C', 'F'}, optional 

8100 Whether to use row-major ('C') or column-major ('FORTRAN') memory 

8101 representation. Default is 'C'. 

8102 

8103 Returns 

8104 ------- 

8105 out : MaskedArray 

8106 MaskedArray interpretation of `a`. 

8107 

8108 See Also 

8109 -------- 

8110 asarray : Similar to `asanyarray`, but does not conserve subclass. 

8111 

8112 Examples 

8113 -------- 

8114 >>> x = np.arange(10.).reshape(2, 5) 

8115 >>> x 

8116 array([[0., 1., 2., 3., 4.], 

8117 [5., 6., 7., 8., 9.]]) 

8118 >>> np.ma.asanyarray(x) 

8119 masked_array( 

8120 data=[[0., 1., 2., 3., 4.], 

8121 [5., 6., 7., 8., 9.]], 

8122 mask=False, 

8123 fill_value=1e+20) 

8124 >>> type(np.ma.asanyarray(x)) 

8125 <class 'numpy.ma.core.MaskedArray'> 

8126 

8127 """ 

8128 # workaround for #8666, to preserve identity. Ideally the bottom line 

8129 # would handle this for us. 

8130 if isinstance(a, MaskedArray) and (dtype is None or dtype == a.dtype): 

8131 return a 

8132 return masked_array(a, dtype=dtype, copy=False, keep_mask=True, subok=True) 

8133 

8134 

8135############################################################################## 

8136# Pickling # 

8137############################################################################## 

8138 

8139 

8140def fromfile(file, dtype=float, count=-1, sep=''): 

8141 raise NotImplementedError( 

8142 "fromfile() not yet implemented for a MaskedArray.") 

8143 

8144 

8145def fromflex(fxarray): 

8146 """ 

8147 Build a masked array from a suitable flexible-type array. 

8148 

8149 The input array has to have a data-type with ``_data`` and ``_mask`` 

8150 fields. This type of array is output by `MaskedArray.toflex`. 

8151 

8152 Parameters 

8153 ---------- 

8154 fxarray : ndarray 

8155 The structured input array, containing ``_data`` and ``_mask`` 

8156 fields. If present, other fields are discarded. 

8157 

8158 Returns 

8159 ------- 

8160 result : MaskedArray 

8161 The constructed masked array. 

8162 

8163 See Also 

8164 -------- 

8165 MaskedArray.toflex : Build a flexible-type array from a masked array. 

8166 

8167 Examples 

8168 -------- 

8169 >>> x = np.ma.array(np.arange(9).reshape(3, 3), mask=[0] + [1, 0] * 4) 

8170 >>> rec = x.toflex() 

8171 >>> rec 

8172 array([[(0, False), (1, True), (2, False)], 

8173 [(3, True), (4, False), (5, True)], 

8174 [(6, False), (7, True), (8, False)]], 

8175 dtype=[('_data', '<i8'), ('_mask', '?')]) 

8176 >>> x2 = np.ma.fromflex(rec) 

8177 >>> x2 

8178 masked_array( 

8179 data=[[0, --, 2], 

8180 [--, 4, --], 

8181 [6, --, 8]], 

8182 mask=[[False, True, False], 

8183 [ True, False, True], 

8184 [False, True, False]], 

8185 fill_value=999999) 

8186 

8187 Extra fields can be present in the structured array but are discarded: 

8188 

8189 >>> dt = [('_data', '<i4'), ('_mask', '|b1'), ('field3', '<f4')] 

8190 >>> rec2 = np.zeros((2, 2), dtype=dt) 

8191 >>> rec2 

8192 array([[(0, False, 0.), (0, False, 0.)], 

8193 [(0, False, 0.), (0, False, 0.)]], 

8194 dtype=[('_data', '<i4'), ('_mask', '?'), ('field3', '<f4')]) 

8195 >>> y = np.ma.fromflex(rec2) 

8196 >>> y 

8197 masked_array( 

8198 data=[[0, 0], 

8199 [0, 0]], 

8200 mask=[[False, False], 

8201 [False, False]], 

8202 fill_value=999999, 

8203 dtype=int32) 

8204 

8205 """ 

8206 return masked_array(fxarray['_data'], mask=fxarray['_mask']) 

8207 

8208 

8209class _convert2ma: 

8210 

8211 """ 

8212 Convert functions from numpy to numpy.ma. 

8213 

8214 Parameters 

8215 ---------- 

8216 _methodname : string 

8217 Name of the method to transform. 

8218 

8219 """ 

8220 __doc__ = None 

8221 

8222 def __init__(self, funcname, np_ret, np_ma_ret, params=None): 

8223 self._func = getattr(np, funcname) 

8224 self.__doc__ = self.getdoc(np_ret, np_ma_ret) 

8225 self._extras = params or {} 

8226 

8227 def getdoc(self, np_ret, np_ma_ret): 

8228 "Return the doc of the function (from the doc of the method)." 

8229 doc = getattr(self._func, '__doc__', None) 

8230 sig = get_object_signature(self._func) 

8231 if doc: 

8232 doc = self._replace_return_type(doc, np_ret, np_ma_ret) 

8233 # Add the signature of the function at the beginning of the doc 

8234 if sig: 

8235 sig = "%s%s\n" % (self._func.__name__, sig) 

8236 doc = sig + doc 

8237 return doc 

8238 

8239 def _replace_return_type(self, doc, np_ret, np_ma_ret): 

8240 """ 

8241 Replace documentation of ``np`` function's return type. 

8242 

8243 Replaces it with the proper type for the ``np.ma`` function. 

8244 

8245 Parameters 

8246 ---------- 

8247 doc : str 

8248 The documentation of the ``np`` method. 

8249 np_ret : str 

8250 The return type string of the ``np`` method that we want to 

8251 replace. (e.g. "out : ndarray") 

8252 np_ma_ret : str 

8253 The return type string of the ``np.ma`` method. 

8254 (e.g. "out : MaskedArray") 

8255 """ 

8256 if np_ret not in doc: 

8257 raise RuntimeError( 

8258 f"Failed to replace `{np_ret}` with `{np_ma_ret}`. " 

8259 f"The documentation string for return type, {np_ret}, is not " 

8260 f"found in the docstring for `np.{self._func.__name__}`. " 

8261 f"Fix the docstring for `np.{self._func.__name__}` or " 

8262 "update the expected string for return type." 

8263 ) 

8264 

8265 return doc.replace(np_ret, np_ma_ret) 

8266 

8267 def __call__(self, *args, **params): 

8268 # Find the common parameters to the call and the definition 

8269 _extras = self._extras 

8270 common_params = set(params).intersection(_extras) 

8271 # Drop the common parameters from the call 

8272 for p in common_params: 

8273 _extras[p] = params.pop(p) 

8274 # Get the result 

8275 result = self._func.__call__(*args, **params).view(MaskedArray) 

8276 if "fill_value" in common_params: 

8277 result.fill_value = _extras.get("fill_value", None) 

8278 if "hardmask" in common_params: 

8279 result._hardmask = bool(_extras.get("hard_mask", False)) 

8280 return result 

8281 

8282 

8283arange = _convert2ma( 

8284 'arange', 

8285 params=dict(fill_value=None, hardmask=False), 

8286 np_ret='arange : ndarray', 

8287 np_ma_ret='arange : MaskedArray', 

8288) 

8289clip = _convert2ma( 

8290 'clip', 

8291 params=dict(fill_value=None, hardmask=False), 

8292 np_ret='clipped_array : ndarray', 

8293 np_ma_ret='clipped_array : MaskedArray', 

8294) 

8295diff = _convert2ma( 

8296 'diff', 

8297 params=dict(fill_value=None, hardmask=False), 

8298 np_ret='diff : ndarray', 

8299 np_ma_ret='diff : MaskedArray', 

8300) 

8301empty = _convert2ma( 

8302 'empty', 

8303 params=dict(fill_value=None, hardmask=False), 

8304 np_ret='out : ndarray', 

8305 np_ma_ret='out : MaskedArray', 

8306) 

8307empty_like = _convert2ma( 

8308 'empty_like', 

8309 np_ret='out : ndarray', 

8310 np_ma_ret='out : MaskedArray', 

8311) 

8312frombuffer = _convert2ma( 

8313 'frombuffer', 

8314 np_ret='out : ndarray', 

8315 np_ma_ret='out: MaskedArray', 

8316) 

8317fromfunction = _convert2ma( 

8318 'fromfunction', 

8319 np_ret='fromfunction : any', 

8320 np_ma_ret='fromfunction: MaskedArray', 

8321) 

8322identity = _convert2ma( 

8323 'identity', 

8324 params=dict(fill_value=None, hardmask=False), 

8325 np_ret='out : ndarray', 

8326 np_ma_ret='out : MaskedArray', 

8327) 

8328indices = _convert2ma( 

8329 'indices', 

8330 params=dict(fill_value=None, hardmask=False), 

8331 np_ret='grid : one ndarray or tuple of ndarrays', 

8332 np_ma_ret='grid : one MaskedArray or tuple of MaskedArrays', 

8333) 

8334ones = _convert2ma( 

8335 'ones', 

8336 params=dict(fill_value=None, hardmask=False), 

8337 np_ret='out : ndarray', 

8338 np_ma_ret='out : MaskedArray', 

8339) 

8340ones_like = _convert2ma( 

8341 'ones_like', 

8342 np_ret='out : ndarray', 

8343 np_ma_ret='out : MaskedArray', 

8344) 

8345squeeze = _convert2ma( 

8346 'squeeze', 

8347 params=dict(fill_value=None, hardmask=False), 

8348 np_ret='squeezed : ndarray', 

8349 np_ma_ret='squeezed : MaskedArray', 

8350) 

8351zeros = _convert2ma( 

8352 'zeros', 

8353 params=dict(fill_value=None, hardmask=False), 

8354 np_ret='out : ndarray', 

8355 np_ma_ret='out : MaskedArray', 

8356) 

8357zeros_like = _convert2ma( 

8358 'zeros_like', 

8359 np_ret='out : ndarray', 

8360 np_ma_ret='out : MaskedArray', 

8361) 

8362 

8363 

8364def append(a, b, axis=None): 

8365 """Append values to the end of an array. 

8366 

8367 .. versionadded:: 1.9.0 

8368 

8369 Parameters 

8370 ---------- 

8371 a : array_like 

8372 Values are appended to a copy of this array. 

8373 b : array_like 

8374 These values are appended to a copy of `a`. It must be of the 

8375 correct shape (the same shape as `a`, excluding `axis`). If `axis` 

8376 is not specified, `b` can be any shape and will be flattened 

8377 before use. 

8378 axis : int, optional 

8379 The axis along which `v` are appended. If `axis` is not given, 

8380 both `a` and `b` are flattened before use. 

8381 

8382 Returns 

8383 ------- 

8384 append : MaskedArray 

8385 A copy of `a` with `b` appended to `axis`. Note that `append` 

8386 does not occur in-place: a new array is allocated and filled. If 

8387 `axis` is None, the result is a flattened array. 

8388 

8389 See Also 

8390 -------- 

8391 numpy.append : Equivalent function in the top-level NumPy module. 

8392 

8393 Examples 

8394 -------- 

8395 >>> import numpy.ma as ma 

8396 >>> a = ma.masked_values([1, 2, 3], 2) 

8397 >>> b = ma.masked_values([[4, 5, 6], [7, 8, 9]], 7) 

8398 >>> ma.append(a, b) 

8399 masked_array(data=[1, --, 3, 4, 5, 6, --, 8, 9], 

8400 mask=[False, True, False, False, False, False, True, False, 

8401 False], 

8402 fill_value=999999) 

8403 """ 

8404 return concatenate([a, b], axis)