Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/numpy/ma/core.py: 21%

2388 statements  

« prev     ^ index     » next       coverage.py v6.4.4, created at 2023-07-17 14:22 -0600

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 import ndarray, amax, amin, iscomplexobj, bool_, _NoValue 

35from numpy import array as narray 

36from numpy.lib.function_base import angle 

37from numpy.compat import ( 

38 getargspec, formatargspec, long, unicode, bytes 

39 ) 

40from numpy import expand_dims 

41from numpy.core.numeric import normalize_axis_tuple 

42 

43 

44__all__ = [ 

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

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

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

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

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

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

51 'choose', 'clip', 'common_fill_value', 'compress', 'compressed', 

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

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

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

55 'expand_dims', 'fabs', 'filled', 'fix_invalid', 'flatten_mask', 

56 'flatten_structured_array', 'floor', 'floor_divide', 'fmod', 

57 'frombuffer', 'fromflex', 'fromfunction', 'getdata', 'getmask', 

58 'getmaskarray', 'greater', 'greater_equal', 'harden_mask', 'hypot', 

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

60 'isMaskedArray', 'is_mask', 'is_masked', 'isarray', 'left_shift', 

61 'less', 'less_equal', 'log', 'log10', 'log2', 

62 'logical_and', 'logical_not', 'logical_or', 'logical_xor', 'make_mask', 

63 'make_mask_descr', 'make_mask_none', 'mask_or', 'masked', 

64 'masked_array', 'masked_equal', 'masked_greater', 

65 'masked_greater_equal', 'masked_inside', 'masked_invalid', 

66 'masked_less', 'masked_less_equal', 'masked_not_equal', 

67 'masked_object', 'masked_outside', 'masked_print_option', 

68 'masked_singleton', 'masked_values', 'masked_where', 'max', 'maximum', 

69 'maximum_fill_value', 'mean', 'min', 'minimum', 'minimum_fill_value', 

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

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

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

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

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

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

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

77 'var', 'where', 'zeros', 'zeros_like', 

78 ] 

79 

80MaskType = np.bool_ 

81nomask = MaskType(0) 

82 

83class MaskedArrayFutureWarning(FutureWarning): 

84 pass 

85 

86def _deprecate_argsort_axis(arr): 

87 """ 

88 Adjust the axis passed to argsort, warning if necessary 

89 

90 Parameters 

91 ---------- 

92 arr 

93 The array which argsort was called on 

94 

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

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

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

98 dimensional, so we only need a warning then. 

99 """ 

100 if arr.ndim <= 1: 

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

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

103 return -1 

104 else: 

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

106 warnings.warn( 

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

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

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

110 MaskedArrayFutureWarning, stacklevel=3) 

111 return None 

112 

113 

114def doc_note(initialdoc, note): 

115 """ 

116 Adds a Notes section to an existing docstring. 

117 

118 """ 

119 if initialdoc is None: 119 ↛ 120line 119 didn't jump to line 120, because the condition on line 119 was never true

120 return 

121 if note is None: 121 ↛ 122line 121 didn't jump to line 122, because the condition on line 121 was never true

122 return initialdoc 

123 

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

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

126 

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

128 

129 

130def get_object_signature(obj): 

131 """ 

132 Get the signature from obj 

133 

134 """ 

135 try: 

136 sig = formatargspec(*getargspec(obj)) 

137 except TypeError: 

138 sig = '' 

139 return sig 

140 

141 

142############################################################################### 

143# Exceptions # 

144############################################################################### 

145 

146 

147class MAError(Exception): 

148 """ 

149 Class for masked array related errors. 

150 

151 """ 

152 pass 

153 

154 

155class MaskError(MAError): 

156 """ 

157 Class for mask related errors. 

158 

159 """ 

160 pass 

161 

162 

163############################################################################### 

164# Filling options # 

165############################################################################### 

166 

167 

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

169default_filler = {'b': True, 

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

171 'f': 1.e20, 

172 'i': 999999, 

173 'O': '?', 

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

175 'u': 999999, 

176 'V': b'???', 

177 'U': u'N/A' 

178 } 

179 

180# Add datetime64 and timedelta64 types 

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

182 "fs", "as"]: 

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

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

185 

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

187 np.csingle, np.cdouble, np.clongdouble] 

188max_filler = ntypes._minvals 

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

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

191 

192min_filler = ntypes._maxvals 

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

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

195 

196del float_types_list 

197 

198def _recursive_fill_value(dtype, f): 

199 """ 

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

201 """ 

202 if dtype.names is not None: 

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

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

205 elif dtype.subdtype: 

206 subtype, shape = dtype.subdtype 

207 subval = _recursive_fill_value(subtype, f) 

208 return np.full(shape, subval) 

209 else: 

210 return f(dtype) 

211 

212 

213def _get_dtype_of(obj): 

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

215 if isinstance(obj, np.dtype): 

216 return obj 

217 elif hasattr(obj, 'dtype'): 

218 return obj.dtype 

219 else: 

220 return np.asanyarray(obj).dtype 

221 

222 

223def default_fill_value(obj): 

224 """ 

225 Return the default fill value for the argument object. 

226 

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

228 array or the type of the input scalar: 

229 

230 ======== ======== 

231 datatype default 

232 ======== ======== 

233 bool True 

234 int 999999 

235 float 1.e20 

236 complex 1.e20+0j 

237 object '?' 

238 string 'N/A' 

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

240 

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

242 default fill value for its type. 

243 

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

245 the default scalar fill value. 

246 

247 Parameters 

248 ---------- 

249 obj : ndarray, dtype or scalar 

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

251 is returned. 

252 

253 Returns 

254 ------- 

255 fill_value : scalar 

256 The default fill value. 

257 

258 Examples 

259 -------- 

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

261 999999 

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

263 1e+20 

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

265 (1e+20+0j) 

266 

267 """ 

268 def _scalar_fill_value(dtype): 

269 if dtype.kind in 'Mm': 

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

271 else: 

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

273 

274 dtype = _get_dtype_of(obj) 

275 return _recursive_fill_value(dtype, _scalar_fill_value) 

276 

277 

278def _extremum_fill_value(obj, extremum, extremum_name): 

279 

280 def _scalar_fill_value(dtype): 

281 try: 

282 return extremum[dtype] 

283 except KeyError as e: 

284 raise TypeError( 

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

286 ) from None 

287 

288 dtype = _get_dtype_of(obj) 

289 return _recursive_fill_value(dtype, _scalar_fill_value) 

290 

291 

292def minimum_fill_value(obj): 

293 """ 

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

295 

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

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

298 

299 Parameters 

300 ---------- 

301 obj : ndarray, dtype or scalar 

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

303 

304 Returns 

305 ------- 

306 val : scalar 

307 The maximum representable value. 

308 

309 Raises 

310 ------ 

311 TypeError 

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

313 

314 See Also 

315 -------- 

316 maximum_fill_value : The inverse function. 

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

318 MaskedArray.fill_value : Return current fill value. 

319 

320 Examples 

321 -------- 

322 >>> import numpy.ma as ma 

323 >>> a = np.int8() 

324 >>> ma.minimum_fill_value(a) 

325 127 

326 >>> a = np.int32() 

327 >>> ma.minimum_fill_value(a) 

328 2147483647 

329 

330 An array of numeric data can also be passed. 

331 

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

333 >>> ma.minimum_fill_value(a) 

334 127 

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

336 >>> ma.minimum_fill_value(a) 

337 inf 

338 

339 """ 

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

341 

342 

343def maximum_fill_value(obj): 

344 """ 

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

346 

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

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

349 

350 Parameters 

351 ---------- 

352 obj : ndarray, dtype or scalar 

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

354 

355 Returns 

356 ------- 

357 val : scalar 

358 The minimum representable value. 

359 

360 Raises 

361 ------ 

362 TypeError 

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

364 

365 See Also 

366 -------- 

367 minimum_fill_value : The inverse function. 

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

369 MaskedArray.fill_value : Return current fill value. 

370 

371 Examples 

372 -------- 

373 >>> import numpy.ma as ma 

374 >>> a = np.int8() 

375 >>> ma.maximum_fill_value(a) 

376 -128 

377 >>> a = np.int32() 

378 >>> ma.maximum_fill_value(a) 

379 -2147483648 

380 

381 An array of numeric data can also be passed. 

382 

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

384 >>> ma.maximum_fill_value(a) 

385 -128 

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

387 >>> ma.maximum_fill_value(a) 

388 -inf 

389 

390 """ 

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

392 

393 

394def _recursive_set_fill_value(fillvalue, dt): 

395 """ 

396 Create a fill value for a structured dtype. 

397 

398 Parameters 

399 ---------- 

400 fillvalue : scalar or array_like 

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

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

403 dt : dtype 

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

405 

406 Returns 

407 ------- 

408 val : tuple 

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

410 

411 """ 

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

413 output_value = [] 

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

415 cdtype = dt[name] 

416 if cdtype.subdtype: 

417 cdtype = cdtype.subdtype[0] 

418 

419 if cdtype.names is not None: 

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

421 else: 

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

423 return tuple(output_value) 

424 

425 

426def _check_fill_value(fill_value, ndtype): 

427 """ 

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

429 

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

431 

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

433 

434 The result is always a 0d array. 

435 

436 """ 

437 ndtype = np.dtype(ndtype) 

438 if fill_value is None: 

439 fill_value = default_fill_value(ndtype) 

440 elif ndtype.names is not None: 

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

442 try: 

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

444 except ValueError as e: 

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

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

447 else: 

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

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

450 dtype=ndtype) 

451 else: 

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

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

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

455 raise TypeError(err_msg % ndtype) 

456 else: 

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

458 # Also in case of converting string arrays. 

459 try: 

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

461 except (OverflowError, ValueError) as e: 

462 # Raise TypeError instead of OverflowError or ValueError. 

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

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

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

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

467 return np.array(fill_value) 

468 

469 

470def set_fill_value(a, fill_value): 

471 """ 

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

473 

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

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

476 doing anything. 

477 

478 Parameters 

479 ---------- 

480 a : array_like 

481 Input array. 

482 fill_value : dtype 

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

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

485 

486 Returns 

487 ------- 

488 None 

489 Nothing returned by this function. 

490 

491 See Also 

492 -------- 

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

494 MaskedArray.fill_value : Return current fill value. 

495 MaskedArray.set_fill_value : Equivalent method. 

496 

497 Examples 

498 -------- 

499 >>> import numpy.ma as ma 

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

501 >>> a 

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

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

504 >>> a 

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

506 mask=[ True, True, True, False, False], 

507 fill_value=999999) 

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

509 >>> a 

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

511 mask=[ True, True, True, False, False], 

512 fill_value=-999) 

513 

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

515 

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

517 >>> a 

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

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

520 >>> a 

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

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

523 >>> a 

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

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

526 >>> a 

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

528 

529 """ 

530 if isinstance(a, MaskedArray): 

531 a.set_fill_value(fill_value) 

532 return 

533 

534 

535def get_fill_value(a): 

536 """ 

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

538 default filling value for that type. 

539 

540 """ 

541 if isinstance(a, MaskedArray): 

542 result = a.fill_value 

543 else: 

544 result = default_fill_value(a) 

545 return result 

546 

547 

548def common_fill_value(a, b): 

549 """ 

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

551 

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

553 otherwise return None. 

554 

555 Parameters 

556 ---------- 

557 a, b : MaskedArray 

558 The masked arrays for which to compare fill values. 

559 

560 Returns 

561 ------- 

562 fill_value : scalar or None 

563 The common fill value, or None. 

564 

565 Examples 

566 -------- 

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

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

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

570 3.0 

571 

572 """ 

573 t1 = get_fill_value(a) 

574 t2 = get_fill_value(b) 

575 if t1 == t2: 

576 return t1 

577 return None 

578 

579 

580def filled(a, fill_value=None): 

581 """ 

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

583 

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

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

586 ``a.fill_value``. 

587 

588 Parameters 

589 ---------- 

590 a : MaskedArray or array_like 

591 An input object. 

592 fill_value : array_like, optional. 

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

594 resulting filled array should be broadcastable 

595 over input array. Default is None. 

596 

597 Returns 

598 ------- 

599 a : ndarray 

600 The filled array. 

601 

602 See Also 

603 -------- 

604 compressed 

605 

606 Examples 

607 -------- 

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

609 ... [1, 0, 0], 

610 ... [0, 0, 0]]) 

611 >>> x.filled() 

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

613 [999999, 4, 5], 

614 [ 6, 7, 8]]) 

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

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

617 [333, 4, 5], 

618 [ 6, 7, 8]]) 

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

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

621 [0, 4, 5], 

622 [6, 7, 8]]) 

623 

624 """ 

625 if hasattr(a, 'filled'): 

626 return a.filled(fill_value) 

627 

628 elif isinstance(a, ndarray): 

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

630 return a 

631 elif isinstance(a, dict): 

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

633 else: 

634 return np.array(a) 

635 

636 

637def get_masked_subclass(*arrays): 

638 """ 

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

640 

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

642 

643 """ 

644 if len(arrays) == 1: 

645 arr = arrays[0] 

646 if isinstance(arr, MaskedArray): 

647 rcls = type(arr) 

648 else: 

649 rcls = MaskedArray 

650 else: 

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

652 rcls = arrcls[0] 

653 if not issubclass(rcls, MaskedArray): 

654 rcls = MaskedArray 

655 for cls in arrcls[1:]: 

656 if issubclass(cls, rcls): 

657 rcls = cls 

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

659 if rcls.__name__ == 'MaskedConstant': 

660 return MaskedArray 

661 return rcls 

662 

663 

664def getdata(a, subok=True): 

665 """ 

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

667 

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

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

670 

671 Parameters 

672 ---------- 

673 a : array_like 

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

675 subok : bool 

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

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

678 

679 See Also 

680 -------- 

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

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

683 

684 Examples 

685 -------- 

686 >>> import numpy.ma as ma 

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

688 >>> a 

689 masked_array( 

690 data=[[1, --], 

691 [3, 4]], 

692 mask=[[False, True], 

693 [False, False]], 

694 fill_value=2) 

695 >>> ma.getdata(a) 

696 array([[1, 2], 

697 [3, 4]]) 

698 

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

700 

701 >>> a.data 

702 array([[1, 2], 

703 [3, 4]]) 

704 

705 """ 

706 try: 

707 data = a._data 

708 except AttributeError: 

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

710 if not subok: 

711 return data.view(ndarray) 

712 return data 

713 

714 

715get_data = getdata 

716 

717 

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

719 """ 

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

721 

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

723 

724 Parameters 

725 ---------- 

726 a : array_like 

727 Input array, a (subclass of) ndarray. 

728 mask : sequence, optional 

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

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

731 copy : bool, optional 

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

733 Default is True. 

734 fill_value : scalar, optional 

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

736 the ``a.fill_value`` is used. 

737 

738 Returns 

739 ------- 

740 b : MaskedArray 

741 The input array with invalid entries fixed. 

742 

743 Notes 

744 ----- 

745 A copy is performed by default. 

746 

747 Examples 

748 -------- 

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

750 >>> x 

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

752 mask=[ True, False, False, False], 

753 fill_value=1e+20) 

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

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

756 mask=[ True, False, True, True], 

757 fill_value=1e+20) 

758 

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

760 >>> fixed.data 

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

762 >>> x.data 

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

764 

765 """ 

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

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

768 if not invalid.any(): 

769 return a 

770 a._mask |= invalid 

771 if fill_value is None: 

772 fill_value = a.fill_value 

773 a._data[invalid] = fill_value 

774 return a 

775 

776def is_string_or_list_of_strings(val): 

777 return (isinstance(val, str) or 

778 (isinstance(val, list) and val and 

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

780 

781############################################################################### 

782# Ufuncs # 

783############################################################################### 

784 

785 

786ufunc_domain = {} 

787ufunc_fills = {} 

788 

789 

790class _DomainCheckInterval: 

791 """ 

792 Define a valid interval, so that : 

793 

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

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

796 

797 """ 

798 

799 def __init__(self, a, b): 

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

801 if a > b: 801 ↛ 802line 801 didn't jump to line 802, because the condition on line 801 was never true

802 (a, b) = (b, a) 

803 self.a = a 

804 self.b = b 

805 

806 def __call__(self, x): 

807 "Execute the call behavior." 

808 # nans at masked positions cause RuntimeWarnings, even though 

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

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

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

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

813 

814 

815class _DomainTan: 

816 """ 

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

818 

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

820 

821 """ 

822 

823 def __init__(self, eps): 

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

825 self.eps = eps 

826 

827 def __call__(self, x): 

828 "Executes the call behavior." 

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

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

831 

832 

833class _DomainSafeDivide: 

834 """ 

835 Define a domain for safe division. 

836 

837 """ 

838 

839 def __init__(self, tolerance=None): 

840 self.tolerance = tolerance 

841 

842 def __call__(self, a, b): 

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

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

845 # component of numpy's import time. 

846 if self.tolerance is None: 

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

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

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

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

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

852 

853 

854class _DomainGreater: 

855 """ 

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

857 

858 """ 

859 

860 def __init__(self, critical_value): 

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

862 self.critical_value = critical_value 

863 

864 def __call__(self, x): 

865 "Executes the call behavior." 

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

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

868 

869 

870class _DomainGreaterEqual: 

871 """ 

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

873 

874 """ 

875 

876 def __init__(self, critical_value): 

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

878 self.critical_value = critical_value 

879 

880 def __call__(self, x): 

881 "Executes the call behavior." 

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

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

884 

885 

886class _MaskedUFunc: 

887 def __init__(self, ufunc): 

888 self.f = ufunc 

889 self.__doc__ = ufunc.__doc__ 

890 self.__name__ = ufunc.__name__ 

891 

892 def __str__(self): 

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

894 

895 

896class _MaskedUnaryOperation(_MaskedUFunc): 

897 """ 

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

899 pre-masked. 

900 

901 Parameters 

902 ---------- 

903 mufunc : callable 

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

905 as ``_MaskedUnaryOperation.f``. 

906 fill : scalar, optional 

907 Filling value, default is 0. 

908 domain : class instance 

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

910 classes. Default is None. 

911 

912 """ 

913 

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

915 super().__init__(mufunc) 

916 self.fill = fill 

917 self.domain = domain 

918 ufunc_domain[mufunc] = domain 

919 ufunc_fills[mufunc] = fill 

920 

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

922 """ 

923 Execute the call behavior. 

924 

925 """ 

926 d = getdata(a) 

927 # Deal with domain 

928 if self.domain is not None: 

929 # Case 1.1. : Domained function 

930 # nans at masked positions cause RuntimeWarnings, even though 

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

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

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

934 # Make a mask 

935 m = ~umath.isfinite(result) 

936 m |= self.domain(d) 

937 m |= getmask(a) 

938 else: 

939 # Case 1.2. : Function without a domain 

940 # Get the result and the mask 

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

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

943 m = getmask(a) 

944 

945 if not result.ndim: 

946 # Case 2.1. : The result is scalarscalar 

947 if m: 

948 return masked 

949 return result 

950 

951 if m is not nomask: 

952 # Case 2.2. The result is an array 

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

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

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

956 

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

958 # equal) 

959 try: 

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

961 except TypeError: 

962 pass 

963 # Transform to 

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

965 masked_result._mask = m 

966 masked_result._update_from(a) 

967 return masked_result 

968 

969 

970class _MaskedBinaryOperation(_MaskedUFunc): 

971 """ 

972 Define masked version of binary operations, where invalid 

973 values are pre-masked. 

974 

975 Parameters 

976 ---------- 

977 mbfunc : function 

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

979 as ``_MaskedBinaryOperation.f``. 

980 domain : class instance 

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

982 classes. Default is None. 

983 fillx : scalar, optional 

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

985 filly : scalar, optional 

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

987 

988 """ 

989 

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

991 """ 

992 abfunc(fillx, filly) must be defined. 

993 

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

995 

996 """ 

997 super().__init__(mbfunc) 

998 self.fillx = fillx 

999 self.filly = filly 

1000 ufunc_domain[mbfunc] = None 

1001 ufunc_fills[mbfunc] = (fillx, filly) 

1002 

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

1004 """ 

1005 Execute the call behavior. 

1006 

1007 """ 

1008 # Get the data, as ndarray 

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

1010 # Get the result 

1011 with np.errstate(): 

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

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

1014 # Get the mask for the result 

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

1016 if ma is nomask: 

1017 if mb is nomask: 

1018 m = nomask 

1019 else: 

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

1021 elif mb is nomask: 

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

1023 else: 

1024 m = umath.logical_or(ma, mb) 

1025 

1026 # Case 1. : scalar 

1027 if not result.ndim: 

1028 if m: 

1029 return masked 

1030 return result 

1031 

1032 # Case 2. : array 

1033 # Revert result to da where masked 

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

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

1036 try: 

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

1038 except Exception: 

1039 pass 

1040 

1041 # Transforms to a (subclass of) MaskedArray 

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

1043 masked_result._mask = m 

1044 if isinstance(a, MaskedArray): 

1045 masked_result._update_from(a) 

1046 elif isinstance(b, MaskedArray): 

1047 masked_result._update_from(b) 

1048 return masked_result 

1049 

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

1051 """ 

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

1053 

1054 """ 

1055 tclass = get_masked_subclass(target) 

1056 m = getmask(target) 

1057 t = filled(target, self.filly) 

1058 if t.shape == (): 

1059 t = t.reshape(1) 

1060 if m is not nomask: 

1061 m = make_mask(m, copy=True) 

1062 m.shape = (1,) 

1063 

1064 if m is nomask: 

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

1066 mr = nomask 

1067 else: 

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

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

1070 

1071 if not tr.shape: 

1072 if mr: 

1073 return masked 

1074 else: 

1075 return tr 

1076 masked_tr = tr.view(tclass) 

1077 masked_tr._mask = mr 

1078 return masked_tr 

1079 

1080 def outer(self, a, b): 

1081 """ 

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

1083 

1084 """ 

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

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

1087 ma = getmask(a) 

1088 mb = getmask(b) 

1089 if ma is nomask and mb is nomask: 

1090 m = nomask 

1091 else: 

1092 ma = getmaskarray(a) 

1093 mb = getmaskarray(b) 

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

1095 if (not m.ndim) and m: 

1096 return masked 

1097 if m is not nomask: 

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

1099 if not d.shape: 

1100 return d 

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

1102 masked_d._mask = m 

1103 return masked_d 

1104 

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

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

1107 value. 

1108 

1109 """ 

1110 tclass = get_masked_subclass(target) 

1111 t = filled(target, self.filly) 

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

1113 masked_result = result.view(tclass) 

1114 return masked_result 

1115 

1116 

1117 

1118class _DomainedBinaryOperation(_MaskedUFunc): 

1119 """ 

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

1121 

1122 They have no reduce, outer or accumulate. 

1123 

1124 Parameters 

1125 ---------- 

1126 mbfunc : function 

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

1128 as ``_DomainedBinaryOperation.f``. 

1129 domain : class instance 

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

1131 classes. 

1132 fillx : scalar, optional 

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

1134 filly : scalar, optional 

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

1136 

1137 """ 

1138 

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

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

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

1142 """ 

1143 super().__init__(dbfunc) 

1144 self.domain = domain 

1145 self.fillx = fillx 

1146 self.filly = filly 

1147 ufunc_domain[dbfunc] = domain 

1148 ufunc_fills[dbfunc] = (fillx, filly) 

1149 

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

1151 "Execute the call behavior." 

1152 # Get the data 

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

1154 # Get the result 

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

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

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

1158 m = ~umath.isfinite(result) 

1159 m |= getmask(a) 

1160 m |= getmask(b) 

1161 # Apply the domain 

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

1163 if domain is not None: 

1164 m |= domain(da, db) 

1165 # Take care of the scalar case first 

1166 if not m.ndim: 

1167 if m: 

1168 return masked 

1169 else: 

1170 return result 

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

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

1173 try: 

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

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

1176 masked_da = umath.multiply(m, da) 

1177 # only add back if it can be cast safely 

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

1179 result += masked_da 

1180 except Exception: 

1181 pass 

1182 

1183 # Transforms to a (subclass of) MaskedArray 

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

1185 masked_result._mask = m 

1186 if isinstance(a, MaskedArray): 

1187 masked_result._update_from(a) 

1188 elif isinstance(b, MaskedArray): 

1189 masked_result._update_from(b) 

1190 return masked_result 

1191 

1192 

1193# Unary ufuncs 

1194exp = _MaskedUnaryOperation(umath.exp) 

1195conjugate = _MaskedUnaryOperation(umath.conjugate) 

1196sin = _MaskedUnaryOperation(umath.sin) 

1197cos = _MaskedUnaryOperation(umath.cos) 

1198arctan = _MaskedUnaryOperation(umath.arctan) 

1199arcsinh = _MaskedUnaryOperation(umath.arcsinh) 

1200sinh = _MaskedUnaryOperation(umath.sinh) 

1201cosh = _MaskedUnaryOperation(umath.cosh) 

1202tanh = _MaskedUnaryOperation(umath.tanh) 

1203abs = absolute = _MaskedUnaryOperation(umath.absolute) 

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

1205fabs = _MaskedUnaryOperation(umath.fabs) 

1206negative = _MaskedUnaryOperation(umath.negative) 

1207floor = _MaskedUnaryOperation(umath.floor) 

1208ceil = _MaskedUnaryOperation(umath.ceil) 

1209around = _MaskedUnaryOperation(np.round_) 

1210logical_not = _MaskedUnaryOperation(umath.logical_not) 

1211 

1212# Domained unary ufuncs 

1213sqrt = _MaskedUnaryOperation(umath.sqrt, 0.0, 

1214 _DomainGreaterEqual(0.0)) 

1215log = _MaskedUnaryOperation(umath.log, 1.0, 

1216 _DomainGreater(0.0)) 

1217log2 = _MaskedUnaryOperation(umath.log2, 1.0, 

1218 _DomainGreater(0.0)) 

1219log10 = _MaskedUnaryOperation(umath.log10, 1.0, 

1220 _DomainGreater(0.0)) 

1221tan = _MaskedUnaryOperation(umath.tan, 0.0, 

1222 _DomainTan(1e-35)) 

1223arcsin = _MaskedUnaryOperation(umath.arcsin, 0.0, 

1224 _DomainCheckInterval(-1.0, 1.0)) 

1225arccos = _MaskedUnaryOperation(umath.arccos, 0.0, 

1226 _DomainCheckInterval(-1.0, 1.0)) 

1227arccosh = _MaskedUnaryOperation(umath.arccosh, 1.0, 

1228 _DomainGreaterEqual(1.0)) 

1229arctanh = _MaskedUnaryOperation(umath.arctanh, 0.0, 

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

1231 

1232# Binary ufuncs 

1233add = _MaskedBinaryOperation(umath.add) 

1234subtract = _MaskedBinaryOperation(umath.subtract) 

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

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

1237equal = _MaskedBinaryOperation(umath.equal) 

1238equal.reduce = None 

1239not_equal = _MaskedBinaryOperation(umath.not_equal) 

1240not_equal.reduce = None 

1241less_equal = _MaskedBinaryOperation(umath.less_equal) 

1242less_equal.reduce = None 

1243greater_equal = _MaskedBinaryOperation(umath.greater_equal) 

1244greater_equal.reduce = None 

1245less = _MaskedBinaryOperation(umath.less) 

1246less.reduce = None 

1247greater = _MaskedBinaryOperation(umath.greater) 

1248greater.reduce = None 

1249logical_and = _MaskedBinaryOperation(umath.logical_and) 

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

1251logical_or = _MaskedBinaryOperation(umath.logical_or) 

1252sometrue = logical_or.reduce 

1253logical_xor = _MaskedBinaryOperation(umath.logical_xor) 

1254bitwise_and = _MaskedBinaryOperation(umath.bitwise_and) 

1255bitwise_or = _MaskedBinaryOperation(umath.bitwise_or) 

1256bitwise_xor = _MaskedBinaryOperation(umath.bitwise_xor) 

1257hypot = _MaskedBinaryOperation(umath.hypot) 

1258 

1259# Domained binary ufuncs 

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

1261true_divide = _DomainedBinaryOperation(umath.true_divide, 

1262 _DomainSafeDivide(), 0, 1) 

1263floor_divide = _DomainedBinaryOperation(umath.floor_divide, 

1264 _DomainSafeDivide(), 0, 1) 

1265remainder = _DomainedBinaryOperation(umath.remainder, 

1266 _DomainSafeDivide(), 0, 1) 

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

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

1269 

1270 

1271############################################################################### 

1272# Mask creation functions # 

1273############################################################################### 

1274 

1275 

1276def _replace_dtype_fields_recursive(dtype, primitive_dtype): 

1277 "Private function allowing recursion in _replace_dtype_fields." 

1278 _recurse = _replace_dtype_fields_recursive 

1279 

1280 # Do we have some name fields ? 

1281 if dtype.names is not None: 1281 ↛ 1282line 1281 didn't jump to line 1282, because the condition on line 1281 was never true

1282 descr = [] 

1283 for name in dtype.names: 

1284 field = dtype.fields[name] 

1285 if len(field) == 3: 

1286 # Prepend the title to the name 

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

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

1289 new_dtype = np.dtype(descr) 

1290 

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

1292 elif dtype.subdtype: 1292 ↛ 1293line 1292 didn't jump to line 1293, because the condition on line 1292 was never true

1293 descr = list(dtype.subdtype) 

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

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

1296 

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

1298 else: 

1299 new_dtype = primitive_dtype 

1300 

1301 # preserve identity of dtypes 

1302 if new_dtype == dtype: 1302 ↛ 1303line 1302 didn't jump to line 1303, because the condition on line 1302 was never true

1303 new_dtype = dtype 

1304 

1305 return new_dtype 

1306 

1307 

1308def _replace_dtype_fields(dtype, primitive_dtype): 

1309 """ 

1310 Construct a dtype description list from a given dtype. 

1311 

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

1313 recursively replaced with `primitive_dtype`. 

1314 

1315 Arguments are coerced to dtypes first. 

1316 """ 

1317 dtype = np.dtype(dtype) 

1318 primitive_dtype = np.dtype(primitive_dtype) 

1319 return _replace_dtype_fields_recursive(dtype, primitive_dtype) 

1320 

1321 

1322def make_mask_descr(ndtype): 

1323 """ 

1324 Construct a dtype description list from a given dtype. 

1325 

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

1327 boolean type. Field names are not altered. 

1328 

1329 Parameters 

1330 ---------- 

1331 ndtype : dtype 

1332 The dtype to convert. 

1333 

1334 Returns 

1335 ------- 

1336 result : dtype 

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

1338 

1339 Examples 

1340 -------- 

1341 >>> import numpy.ma as ma 

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

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

1344 >>> dtype 

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

1346 >>> ma.make_mask_descr(dtype) 

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

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

1349 dtype('bool') 

1350 

1351 """ 

1352 return _replace_dtype_fields(ndtype, MaskType) 

1353 

1354 

1355def getmask(a): 

1356 """ 

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

1358 

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

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

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

1362 

1363 Parameters 

1364 ---------- 

1365 a : array_like 

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

1367 

1368 See Also 

1369 -------- 

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

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

1372 

1373 Examples 

1374 -------- 

1375 >>> import numpy.ma as ma 

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

1377 >>> a 

1378 masked_array( 

1379 data=[[1, --], 

1380 [3, 4]], 

1381 mask=[[False, True], 

1382 [False, False]], 

1383 fill_value=2) 

1384 >>> ma.getmask(a) 

1385 array([[False, True], 

1386 [False, False]]) 

1387 

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

1389 

1390 >>> a.mask 

1391 array([[False, True], 

1392 [False, False]]) 

1393 

1394 Result when mask == `nomask` 

1395 

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

1397 >>> b 

1398 masked_array( 

1399 data=[[1, 2], 

1400 [3, 4]], 

1401 mask=False, 

1402 fill_value=999999) 

1403 >>> ma.nomask 

1404 False 

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

1406 True 

1407 >>> b.mask == ma.nomask 

1408 True 

1409 

1410 """ 

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

1412 

1413 

1414get_mask = getmask 

1415 

1416 

1417def getmaskarray(arr): 

1418 """ 

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

1420 

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

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

1423 the same shape as `arr`. 

1424 

1425 Parameters 

1426 ---------- 

1427 arr : array_like 

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

1429 

1430 See Also 

1431 -------- 

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

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

1434 

1435 Examples 

1436 -------- 

1437 >>> import numpy.ma as ma 

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

1439 >>> a 

1440 masked_array( 

1441 data=[[1, --], 

1442 [3, 4]], 

1443 mask=[[False, True], 

1444 [False, False]], 

1445 fill_value=2) 

1446 >>> ma.getmaskarray(a) 

1447 array([[False, True], 

1448 [False, False]]) 

1449 

1450 Result when mask == ``nomask`` 

1451 

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

1453 >>> b 

1454 masked_array( 

1455 data=[[1, 2], 

1456 [3, 4]], 

1457 mask=False, 

1458 fill_value=999999) 

1459 >>> ma.getmaskarray(b) 

1460 array([[False, False], 

1461 [False, False]]) 

1462 

1463 """ 

1464 mask = getmask(arr) 

1465 if mask is nomask: 

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

1467 return mask 

1468 

1469 

1470def is_mask(m): 

1471 """ 

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

1473 

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

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

1476 mask has a flexible dtype. 

1477 

1478 Parameters 

1479 ---------- 

1480 m : array_like 

1481 Array to test. 

1482 

1483 Returns 

1484 ------- 

1485 result : bool 

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

1487 

1488 See Also 

1489 -------- 

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

1491 

1492 Examples 

1493 -------- 

1494 >>> import numpy.ma as ma 

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

1496 >>> m 

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

1498 mask=[ True, False, True, False, False], 

1499 fill_value=0) 

1500 >>> ma.is_mask(m) 

1501 False 

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

1503 True 

1504 

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

1506 for it to be considered a valid mask. 

1507 

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

1509 >>> ma.is_mask(m) 

1510 False 

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

1512 >>> m 

1513 array([False, True, False]) 

1514 >>> ma.is_mask(m) 

1515 True 

1516 

1517 Arrays with complex dtypes don't return True. 

1518 

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

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

1521 >>> dtype 

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

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

1524 ... dtype=dtype) 

1525 >>> m 

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

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

1528 >>> ma.is_mask(m) 

1529 False 

1530 

1531 """ 

1532 try: 

1533 return m.dtype.type is MaskType 

1534 except AttributeError: 

1535 return False 

1536 

1537 

1538def _shrink_mask(m): 

1539 """ 

1540 Shrink a mask to nomask if possible 

1541 """ 

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

1543 return nomask 

1544 else: 

1545 return m 

1546 

1547 

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

1549 """ 

1550 Create a boolean mask from an array. 

1551 

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

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

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

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

1556 

1557 Parameters 

1558 ---------- 

1559 m : array_like 

1560 Potential mask. 

1561 copy : bool, optional 

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

1563 shrink : bool, optional 

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

1565 dtype : dtype, optional 

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

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

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

1569 case ``nomask`` is always returned. 

1570 

1571 Returns 

1572 ------- 

1573 result : ndarray 

1574 A boolean mask derived from `m`. 

1575 

1576 Examples 

1577 -------- 

1578 >>> import numpy.ma as ma 

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

1580 >>> ma.make_mask(m) 

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

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

1583 >>> ma.make_mask(m) 

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

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

1586 >>> ma.make_mask(m) 

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

1588 

1589 Effect of the `shrink` parameter. 

1590 

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

1592 >>> m 

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

1594 >>> ma.make_mask(m) 

1595 False 

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

1597 array([False, False, False, False]) 

1598 

1599 Using a flexible `dtype`. 

1600 

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

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

1603 >>> arr = [] 

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

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

1606 >>> arr 

1607 [(1, 0), (0, 1), (1, 0), (1, 0)] 

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

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

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

1611 >>> arr 

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

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

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

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

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

1617 

1618 """ 

1619 if m is nomask: 

1620 return nomask 

1621 

1622 # Make sure the input dtype is valid. 

1623 dtype = make_mask_descr(dtype) 

1624 

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

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

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

1628 

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

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

1631 # Bas les masques ! 

1632 if shrink: 

1633 result = _shrink_mask(result) 

1634 return result 

1635 

1636 

1637def make_mask_none(newshape, dtype=None): 

1638 """ 

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

1640 

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

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

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

1644 

1645 Parameters 

1646 ---------- 

1647 newshape : tuple 

1648 A tuple indicating the shape of the mask. 

1649 dtype : {None, dtype}, optional 

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

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

1652 

1653 Returns 

1654 ------- 

1655 result : ndarray 

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

1657 

1658 See Also 

1659 -------- 

1660 make_mask : Create a boolean mask from an array. 

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

1662 

1663 Examples 

1664 -------- 

1665 >>> import numpy.ma as ma 

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

1667 array([False, False, False]) 

1668 

1669 Defining a more complex dtype. 

1670 

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

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

1673 >>> dtype 

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

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

1676 array([(False, False), (False, False), (False, False)], 

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

1678 

1679 """ 

1680 if dtype is None: 

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

1682 else: 

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

1684 return result 

1685 

1686 

1687def _recursive_mask_or(m1, m2, newmask): 

1688 names = m1.dtype.names 

1689 for name in names: 

1690 current1 = m1[name] 

1691 if current1.dtype.names is not None: 

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

1693 else: 

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

1695 

1696 

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

1698 """ 

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

1700 

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

1702 (i.e. False). 

1703 

1704 Parameters 

1705 ---------- 

1706 m1, m2 : array_like 

1707 Input masks. 

1708 copy : bool, optional 

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

1710 of the other input mask. Defaults to False. 

1711 shrink : bool, optional 

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

1713 False. Defaults to True. 

1714 

1715 Returns 

1716 ------- 

1717 mask : output mask 

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

1719 

1720 Raises 

1721 ------ 

1722 ValueError 

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

1724 

1725 Examples 

1726 -------- 

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

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

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

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

1731 

1732 """ 

1733 

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

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

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

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

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

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

1740 if m1 is m2 and is_mask(m1): 

1741 return m1 

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

1743 if dtype1 != dtype2: 

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

1745 if dtype1.names is not None: 

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

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

1748 _recursive_mask_or(m1, m2, newmask) 

1749 return newmask 

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

1751 

1752 

1753def flatten_mask(mask): 

1754 """ 

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

1756 are collapsed. 

1757 

1758 Parameters 

1759 ---------- 

1760 mask : array_like 

1761 Input array, which will be interpreted as booleans. 

1762 

1763 Returns 

1764 ------- 

1765 flattened_mask : ndarray of bools 

1766 The flattened input. 

1767 

1768 Examples 

1769 -------- 

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

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

1772 array([False, False, True]) 

1773 

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

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

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

1777 

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

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

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

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

1782 

1783 """ 

1784 

1785 def _flatmask(mask): 

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

1787 mnames = mask.dtype.names 

1788 if mnames is not None: 

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

1790 else: 

1791 return mask 

1792 

1793 def _flatsequence(sequence): 

1794 "Generates a flattened version of the sequence." 

1795 try: 

1796 for element in sequence: 

1797 if hasattr(element, '__iter__'): 

1798 yield from _flatsequence(element) 

1799 else: 

1800 yield element 

1801 except TypeError: 

1802 yield sequence 

1803 

1804 mask = np.asarray(mask) 

1805 flattened = _flatsequence(_flatmask(mask)) 

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

1807 

1808 

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

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

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

1812 if mask is not nomask: 

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

1814 return nomask 

1815 

1816 

1817############################################################################### 

1818# Masking functions # 

1819############################################################################### 

1820 

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

1822 """ 

1823 Mask an array where a condition is met. 

1824 

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

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

1827 

1828 Parameters 

1829 ---------- 

1830 condition : array_like 

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

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

1833 a : array_like 

1834 Array to mask. 

1835 copy : bool 

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

1837 `a` in place and return a view. 

1838 

1839 Returns 

1840 ------- 

1841 result : MaskedArray 

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

1843 

1844 See Also 

1845 -------- 

1846 masked_values : Mask using floating point equality. 

1847 masked_equal : Mask where equal to a given value. 

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

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

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

1851 masked_less : Mask where less than a given value. 

1852 masked_greater : Mask where greater than a given value. 

1853 masked_inside : Mask inside a given interval. 

1854 masked_outside : Mask outside a given interval. 

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

1856 

1857 Examples 

1858 -------- 

1859 >>> import numpy.ma as ma 

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

1861 >>> a 

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

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

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

1865 mask=[ True, True, True, False], 

1866 fill_value=999999) 

1867 

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

1869 

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

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

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

1873 mask=[False, False, True, False], 

1874 fill_value='N/A', 

1875 dtype='<U1') 

1876 

1877 Effect of the `copy` argument. 

1878 

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

1880 >>> c 

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

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

1883 fill_value=999999) 

1884 >>> c[0] = 99 

1885 >>> c 

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

1887 mask=[False, True, True, False], 

1888 fill_value=999999) 

1889 >>> a 

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

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

1892 >>> c[0] = 99 

1893 >>> c 

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

1895 mask=[False, True, True, False], 

1896 fill_value=999999) 

1897 >>> a 

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

1899 

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

1901 

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

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

1904 >>> a 

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

1906 mask=[False, False, True, False], 

1907 fill_value=999999) 

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

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

1910 >>> b 

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

1912 mask=[ True, False, False, False], 

1913 fill_value=999999) 

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

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

1916 mask=[ True, False, True, True], 

1917 fill_value=999999) 

1918 

1919 """ 

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

1921 cond = make_mask(condition, shrink=False) 

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

1923 

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

1925 if cshape and cshape != ashape: 

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

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

1928 if hasattr(a, '_mask'): 

1929 cond = mask_or(cond, a._mask) 

1930 cls = type(a) 

1931 else: 

1932 cls = MaskedArray 

1933 result = a.view(cls) 

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

1935 result.mask = _shrink_mask(cond) 

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

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

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

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

1940 return result 

1941 

1942 

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

1944 """ 

1945 Mask an array where greater than a given value. 

1946 

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

1948 `condition` = (x > value). 

1949 

1950 See Also 

1951 -------- 

1952 masked_where : Mask where a condition is met. 

1953 

1954 Examples 

1955 -------- 

1956 >>> import numpy.ma as ma 

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

1958 >>> a 

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

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

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

1962 mask=[False, False, False, True], 

1963 fill_value=999999) 

1964 

1965 """ 

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

1967 

1968 

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

1970 """ 

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

1972 

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

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

1975 

1976 See Also 

1977 -------- 

1978 masked_where : Mask where a condition is met. 

1979 

1980 Examples 

1981 -------- 

1982 >>> import numpy.ma as ma 

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

1984 >>> a 

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

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

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

1988 mask=[False, False, True, True], 

1989 fill_value=999999) 

1990 

1991 """ 

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

1993 

1994 

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

1996 """ 

1997 Mask an array where less than a given value. 

1998 

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

2000 `condition` = (x < value). 

2001 

2002 See Also 

2003 -------- 

2004 masked_where : Mask where a condition is met. 

2005 

2006 Examples 

2007 -------- 

2008 >>> import numpy.ma as ma 

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

2010 >>> a 

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

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

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

2014 mask=[ True, True, False, False], 

2015 fill_value=999999) 

2016 

2017 """ 

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

2019 

2020 

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

2022 """ 

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

2024 

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

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

2027 

2028 See Also 

2029 -------- 

2030 masked_where : Mask where a condition is met. 

2031 

2032 Examples 

2033 -------- 

2034 >>> import numpy.ma as ma 

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

2036 >>> a 

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

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

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

2040 mask=[ True, True, True, False], 

2041 fill_value=999999) 

2042 

2043 """ 

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

2045 

2046 

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

2048 """ 

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

2050 

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

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

2053 

2054 See Also 

2055 -------- 

2056 masked_where : Mask where a condition is met. 

2057 

2058 Examples 

2059 -------- 

2060 >>> import numpy.ma as ma 

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

2062 >>> a 

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

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

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

2066 mask=[ True, True, False, True], 

2067 fill_value=999999) 

2068 

2069 """ 

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

2071 

2072 

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

2074 """ 

2075 Mask an array where equal to a given value. 

2076 

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

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

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

2080 

2081 See Also 

2082 -------- 

2083 masked_where : Mask where a condition is met. 

2084 masked_values : Mask using floating point equality. 

2085 

2086 Examples 

2087 -------- 

2088 >>> import numpy.ma as ma 

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

2090 >>> a 

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

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

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

2094 mask=[False, False, True, False], 

2095 fill_value=2) 

2096 

2097 """ 

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

2099 output.fill_value = value 

2100 return output 

2101 

2102 

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

2104 """ 

2105 Mask an array inside a given interval. 

2106 

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

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

2109 can be given in either order. 

2110 

2111 See Also 

2112 -------- 

2113 masked_where : Mask where a condition is met. 

2114 

2115 Notes 

2116 ----- 

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

2118 

2119 Examples 

2120 -------- 

2121 >>> import numpy.ma as ma 

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

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

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

2125 mask=[False, False, True, True, False, False], 

2126 fill_value=1e+20) 

2127 

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

2129 

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

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

2132 mask=[False, False, True, True, False, False], 

2133 fill_value=1e+20) 

2134 

2135 """ 

2136 if v2 < v1: 

2137 (v1, v2) = (v2, v1) 

2138 xf = filled(x) 

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

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

2141 

2142 

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

2144 """ 

2145 Mask an array outside a given interval. 

2146 

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

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

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

2150 

2151 See Also 

2152 -------- 

2153 masked_where : Mask where a condition is met. 

2154 

2155 Notes 

2156 ----- 

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

2158 

2159 Examples 

2160 -------- 

2161 >>> import numpy.ma as ma 

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

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

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

2165 mask=[ True, True, False, False, True, True], 

2166 fill_value=1e+20) 

2167 

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

2169 

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

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

2172 mask=[ True, True, False, False, True, True], 

2173 fill_value=1e+20) 

2174 

2175 """ 

2176 if v2 < v1: 

2177 (v1, v2) = (v2, v1) 

2178 xf = filled(x) 

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

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

2181 

2182 

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

2184 """ 

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

2186 

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

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

2189 

2190 Parameters 

2191 ---------- 

2192 x : array_like 

2193 Array to mask 

2194 value : object 

2195 Comparison value 

2196 copy : {True, False}, optional 

2197 Whether to return a copy of `x`. 

2198 shrink : {True, False}, optional 

2199 Whether to collapse a mask full of False to nomask 

2200 

2201 Returns 

2202 ------- 

2203 result : MaskedArray 

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

2205 

2206 See Also 

2207 -------- 

2208 masked_where : Mask where a condition is met. 

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

2210 masked_values : Mask using floating point equality. 

2211 

2212 Examples 

2213 -------- 

2214 >>> import numpy.ma as ma 

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

2216 >>> # don't eat spoiled food 

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

2218 >>> eat 

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

2220 mask=[ True, False], 

2221 fill_value='green_eggs', 

2222 dtype=object) 

2223 >>> # plain ol` ham is boring 

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

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

2226 >>> eat 

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

2228 mask=False, 

2229 fill_value='green_eggs', 

2230 dtype=object) 

2231 

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

2233 

2234 >>> eat 

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

2236 mask=False, 

2237 fill_value='green_eggs', 

2238 dtype=object) 

2239 

2240 """ 

2241 if isMaskedArray(x): 

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

2243 mask = x._mask 

2244 else: 

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

2246 mask = nomask 

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

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

2249 

2250 

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

2252 """ 

2253 Mask using floating point equality. 

2254 

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

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

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

2258 

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

2260 `masked_equal`. 

2261 

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

2263 possible. 

2264 

2265 Parameters 

2266 ---------- 

2267 x : array_like 

2268 Array to mask. 

2269 value : float 

2270 Masking value. 

2271 rtol, atol : float, optional 

2272 Tolerance parameters passed on to `isclose` 

2273 copy : bool, optional 

2274 Whether to return a copy of `x`. 

2275 shrink : bool, optional 

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

2277 

2278 Returns 

2279 ------- 

2280 result : MaskedArray 

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

2282 

2283 See Also 

2284 -------- 

2285 masked_where : Mask where a condition is met. 

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

2287 

2288 Examples 

2289 -------- 

2290 >>> import numpy.ma as ma 

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

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

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

2294 mask=[False, True, False, True, False], 

2295 fill_value=1.1) 

2296 

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

2298 

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

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

2301 mask=False, 

2302 fill_value=1.5) 

2303 

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

2305 result of ``masked_equal``. 

2306 

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

2308 >>> x 

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

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

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

2312 mask=[False, False, True, False, False], 

2313 fill_value=2) 

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

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

2316 mask=[False, False, True, False, False], 

2317 fill_value=2) 

2318 

2319 """ 

2320 xnew = filled(x, value) 

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

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

2323 else: 

2324 mask = umath.equal(xnew, value) 

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

2326 if shrink: 

2327 ret.shrink_mask() 

2328 return ret 

2329 

2330 

2331def masked_invalid(a, copy=True): 

2332 """ 

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

2334 

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

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

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

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

2339 

2340 See Also 

2341 -------- 

2342 masked_where : Mask where a condition is met. 

2343 

2344 Examples 

2345 -------- 

2346 >>> import numpy.ma as ma 

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

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

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

2350 >>> a 

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

2352 >>> ma.masked_invalid(a) 

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

2354 mask=[False, False, True, True, False], 

2355 fill_value=1e+20) 

2356 

2357 """ 

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

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

2360 if mask is not None: 

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

2362 if mask is not nomask: 

2363 condition |= mask 

2364 cls = type(a) 

2365 else: 

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

2367 cls = MaskedArray 

2368 result = a.view(cls) 

2369 result._mask = condition 

2370 return result 

2371 

2372 

2373############################################################################### 

2374# Printing options # 

2375############################################################################### 

2376 

2377 

2378class _MaskedPrintOption: 

2379 """ 

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

2381 

2382 """ 

2383 

2384 def __init__(self, display): 

2385 """ 

2386 Create the masked_print_option object. 

2387 

2388 """ 

2389 self._display = display 

2390 self._enabled = True 

2391 

2392 def display(self): 

2393 """ 

2394 Display the string to print for masked values. 

2395 

2396 """ 

2397 return self._display 

2398 

2399 def set_display(self, s): 

2400 """ 

2401 Set the string to print for masked values. 

2402 

2403 """ 

2404 self._display = s 

2405 

2406 def enabled(self): 

2407 """ 

2408 Is the use of the display value enabled? 

2409 

2410 """ 

2411 return self._enabled 

2412 

2413 def enable(self, shrink=1): 

2414 """ 

2415 Set the enabling shrink to `shrink`. 

2416 

2417 """ 

2418 self._enabled = shrink 

2419 

2420 def __str__(self): 

2421 return str(self._display) 

2422 

2423 __repr__ = __str__ 

2424 

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

2426masked_print_option = _MaskedPrintOption('--') 

2427 

2428 

2429def _recursive_printoption(result, mask, printopt): 

2430 """ 

2431 Puts printoptions in result where mask is True. 

2432 

2433 Private function allowing for recursion 

2434 

2435 """ 

2436 names = result.dtype.names 

2437 if names is not None: 

2438 for name in names: 

2439 curdata = result[name] 

2440 curmask = mask[name] 

2441 _recursive_printoption(curdata, curmask, printopt) 

2442 else: 

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

2444 return 

2445 

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

2447_legacy_print_templates = dict( 

2448 long_std=textwrap.dedent("""\ 

2449 masked_%(name)s(data = 

2450 %(data)s, 

2451 %(nlen)s mask = 

2452 %(mask)s, 

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

2454 """), 

2455 long_flx=textwrap.dedent("""\ 

2456 masked_%(name)s(data = 

2457 %(data)s, 

2458 %(nlen)s mask = 

2459 %(mask)s, 

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

2461 %(nlen)s dtype = %(dtype)s) 

2462 """), 

2463 short_std=textwrap.dedent("""\ 

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

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

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

2467 """), 

2468 short_flx=textwrap.dedent("""\ 

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

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

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

2472 %(nlen)s dtype = %(dtype)s) 

2473 """) 

2474) 

2475 

2476############################################################################### 

2477# MaskedArray class # 

2478############################################################################### 

2479 

2480 

2481def _recursive_filled(a, mask, fill_value): 

2482 """ 

2483 Recursively fill `a` with `fill_value`. 

2484 

2485 """ 

2486 names = a.dtype.names 

2487 for name in names: 

2488 current = a[name] 

2489 if current.dtype.names is not None: 

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

2491 else: 

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

2493 

2494 

2495def flatten_structured_array(a): 

2496 """ 

2497 Flatten a structured array. 

2498 

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

2500 (nested) fields. 

2501 

2502 Parameters 

2503 ---------- 

2504 a : structured array 

2505 

2506 Returns 

2507 ------- 

2508 output : masked array or ndarray 

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

2510 standard ndarray. 

2511 

2512 Examples 

2513 -------- 

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

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

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

2517 array([[1., 1.], 

2518 [2., 2.]]) 

2519 

2520 """ 

2521 

2522 def flatten_sequence(iterable): 

2523 """ 

2524 Flattens a compound of nested iterables. 

2525 

2526 """ 

2527 for elm in iter(iterable): 

2528 if hasattr(elm, '__iter__'): 

2529 yield from flatten_sequence(elm) 

2530 else: 

2531 yield elm 

2532 

2533 a = np.asanyarray(a) 

2534 inishape = a.shape 

2535 a = a.ravel() 

2536 if isinstance(a, MaskedArray): 

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

2538 out = out.view(MaskedArray) 

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

2540 for d in getmaskarray(a)]) 

2541 else: 

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

2543 if len(inishape) > 1: 

2544 newshape = list(out.shape) 

2545 newshape[0] = inishape 

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

2547 return out 

2548 

2549 

2550def _arraymethod(funcname, onmask=True): 

2551 """ 

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

2553 

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

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

2556 on the original ``_data``. 

2557 

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

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

2560 to the initial mask. 

2561 

2562 Parameters 

2563 ---------- 

2564 funcname : str 

2565 Name of the function to apply on data. 

2566 onmask : bool 

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

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

2569 attribute. 

2570 

2571 Returns 

2572 ------- 

2573 method : instancemethod 

2574 Class method wrapper of the specified basic array method. 

2575 

2576 """ 

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

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

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

2580 result._update_from(self) 

2581 mask = self._mask 

2582 if not onmask: 

2583 result.__setmask__(mask) 

2584 elif mask is not nomask: 

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

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

2587 return result 

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

2589 if methdoc is not None: 2589 ↛ 2591line 2589 didn't jump to line 2591, because the condition on line 2589 was never false

2590 wrapped_method.__doc__ = methdoc.__doc__ 

2591 wrapped_method.__name__ = funcname 

2592 return wrapped_method 

2593 

2594 

2595class MaskedIterator: 

2596 """ 

2597 Flat iterator object to iterate over masked arrays. 

2598 

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

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

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

2602 

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

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

2605 advanced indexing. 

2606 

2607 See Also 

2608 -------- 

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

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

2611 

2612 Notes 

2613 ----- 

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

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

2616 

2617 Examples 

2618 -------- 

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

2620 >>> fl = x.flat 

2621 >>> type(fl) 

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

2623 >>> for item in fl: 

2624 ... print(item) 

2625 ... 

2626 0 

2627 1 

2628 2 

2629 3 

2630 4 

2631 5 

2632 

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

2634 returns a masked array: 

2635 

2636 >>> fl[2:4] 

2637 masked_array(data = [2 3], 

2638 mask = False, 

2639 fill_value = 999999) 

2640 

2641 """ 

2642 

2643 def __init__(self, ma): 

2644 self.ma = ma 

2645 self.dataiter = ma._data.flat 

2646 

2647 if ma._mask is nomask: 

2648 self.maskiter = None 

2649 else: 

2650 self.maskiter = ma._mask.flat 

2651 

2652 def __iter__(self): 

2653 return self 

2654 

2655 def __getitem__(self, indx): 

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

2657 if self.maskiter is not None: 

2658 _mask = self.maskiter.__getitem__(indx) 

2659 if isinstance(_mask, ndarray): 

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

2661 _mask.shape = result.shape 

2662 result._mask = _mask 

2663 elif isinstance(_mask, np.void): 

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

2665 elif _mask: # Just a scalar, masked 

2666 return masked 

2667 return result 

2668 

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

2670 def __setitem__(self, index, value): 

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

2672 if self.maskiter is not None: 

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

2674 

2675 def __next__(self): 

2676 """ 

2677 Return the next value, or raise StopIteration. 

2678 

2679 Examples 

2680 -------- 

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

2682 >>> fl = x.flat 

2683 >>> next(fl) 

2684 3 

2685 >>> next(fl) 

2686 masked 

2687 >>> next(fl) 

2688 Traceback (most recent call last): 

2689 ... 

2690 StopIteration 

2691 

2692 """ 

2693 d = next(self.dataiter) 

2694 if self.maskiter is not None: 

2695 m = next(self.maskiter) 

2696 if isinstance(m, np.void): 

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

2698 elif m: # Just a scalar, masked 

2699 return masked 

2700 return d 

2701 

2702 

2703class MaskedArray(ndarray): 

2704 """ 

2705 An array class with possibly masked values. 

2706 

2707 Masked values of True exclude the corresponding element from any 

2708 computation. 

2709 

2710 Construction:: 

2711 

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

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

2714 shrink=True, order=None) 

2715 

2716 Parameters 

2717 ---------- 

2718 data : array_like 

2719 Input data. 

2720 mask : sequence, optional 

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

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

2723 dtype : dtype, optional 

2724 Data type of the output. 

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

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

2727 a copy is performed. 

2728 copy : bool, optional 

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

2730 Default is False. 

2731 subok : bool, optional 

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

2733 plain `MaskedArray`. Default is True. 

2734 ndmin : int, optional 

2735 Minimum number of dimensions. Default is 0. 

2736 fill_value : scalar, optional 

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

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

2739 keep_mask : bool, optional 

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

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

2742 hard_mask : bool, optional 

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

2744 cannot be unmasked. Default is False. 

2745 shrink : bool, optional 

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

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

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

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

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

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

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

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

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

2755 

2756 Examples 

2757 -------- 

2758 

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

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

2761 

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

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

2764 ... [False, False, True]]) 

2765 masked_array( 

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

2767 [3, 4, --]], 

2768 mask=[[False, True, False], 

2769 [False, False, True]], 

2770 fill_value=999999) 

2771 

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

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

2774 boolean value: 

2775 

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

2777 masked_array( 

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

2779 [3, 4, 5]], 

2780 mask=[[False, False, False], 

2781 [False, False, False]], 

2782 fill_value=999999) 

2783 

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

2785 masked_array( 

2786 data=[[--, --, --], 

2787 [--, --, --]], 

2788 mask=[[ True, True, True], 

2789 [ True, True, True]], 

2790 fill_value=999999, 

2791 dtype=int64) 

2792 

2793 .. note:: 

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

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

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

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

2798 

2799 >>> np.False_ is np.ma.nomask 

2800 True 

2801 

2802 """ 

2803 

2804 __array_priority__ = 15 

2805 _defaultmask = nomask 

2806 _defaulthardmask = False 

2807 _baseclass = ndarray 

2808 

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

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

2811 _print_width = 100 

2812 _print_width_1d = 1500 

2813 

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

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

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

2817 """ 

2818 Create a new masked array from scratch. 

2819 

2820 Notes 

2821 ----- 

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

2823 

2824 """ 

2825 # Process data. 

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

2827 order=order, subok=True, ndmin=ndmin) 

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

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

2830 if isinstance(data, MaskedArray) and (data.shape != _data.shape): 2830 ↛ 2831line 2830 didn't jump to line 2831, because the condition on line 2830 was never true

2831 copy = True 

2832 

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

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

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

2836 if isinstance(data, cls) and subok and not isinstance(data, MaskedConstant): 2836 ↛ 2837line 2836 didn't jump to line 2837, because the condition on line 2836 was never true

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

2838 else: 

2839 _data = ndarray.view(_data, cls) 

2840 

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

2842 # still has the _mask attribute like MaskedArrays 

2843 if hasattr(data, '_mask') and not isinstance(data, ndarray): 2843 ↛ 2844line 2843 didn't jump to line 2844, because the condition on line 2843 was never true

2844 _data._mask = data._mask 

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

2846 # Process mask. 

2847 # Type of the mask 

2848 mdtype = make_mask_descr(_data.dtype) 

2849 

2850 if mask is nomask: 2850 ↛ 2853line 2850 didn't jump to line 2853, because the condition on line 2850 was never true

2851 # Case 1. : no mask in input. 

2852 # Erase the current mask ? 

2853 if not keep_mask: 

2854 # With a reduced version 

2855 if shrink: 

2856 _data._mask = nomask 

2857 # With full version 

2858 else: 

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

2860 # Check whether we missed something 

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

2862 try: 

2863 # If data is a sequence of masked array 

2864 mask = np.array( 

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

2866 for m in data], dtype=mdtype) 

2867 except ValueError: 

2868 # If data is nested 

2869 mask = nomask 

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

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

2872 _data._mask = mask 

2873 _data._sharedmask = False 

2874 else: 

2875 _data._sharedmask = not copy 

2876 if copy: 

2877 _data._mask = _data._mask.copy() 

2878 # Reset the shape of the original mask 

2879 if getmask(data) is not nomask: 

2880 data._mask.shape = data.shape 

2881 else: 

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

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

2884 if mask is True and mdtype == MaskType: 2884 ↛ 2885line 2884 didn't jump to line 2885, because the condition on line 2884 was never true

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

2886 elif mask is False and mdtype == MaskType: 2886 ↛ 2887line 2886 didn't jump to line 2887, because the condition on line 2886 was never true

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

2888 else: 

2889 # Read the mask with the current mdtype 

2890 try: 

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

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

2893 except TypeError: 

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

2895 dtype=mdtype) 

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

2897 if mask.shape != _data.shape: 2897 ↛ 2898line 2897 didn't jump to line 2898, because the condition on line 2897 was never true

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

2899 if nm == 1: 

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

2901 elif nm == nd: 

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

2903 else: 

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

2905 "mask size is %i." 

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

2907 copy = True 

2908 # Set the mask to the new value 

2909 if _data._mask is nomask: 2909 ↛ 2913line 2909 didn't jump to line 2913, because the condition on line 2909 was never false

2910 _data._mask = mask 

2911 _data._sharedmask = not copy 

2912 else: 

2913 if not keep_mask: 

2914 _data._mask = mask 

2915 _data._sharedmask = not copy 

2916 else: 

2917 if _data.dtype.names is not None: 

2918 def _recursive_or(a, b): 

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

2920 for name in a.dtype.names: 

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

2922 if af.dtype.names is not None: 

2923 _recursive_or(af, bf) 

2924 else: 

2925 af |= bf 

2926 

2927 _recursive_or(_data._mask, mask) 

2928 else: 

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

2930 _data._sharedmask = False 

2931 # Update fill_value. 

2932 if fill_value is None: 2932 ↛ 2935line 2932 didn't jump to line 2935, because the condition on line 2932 was never false

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

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

2935 if fill_value is not None: 2935 ↛ 2936line 2935 didn't jump to line 2936, because the condition on line 2935 was never true

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

2937 # Process extra options .. 

2938 if hard_mask is None: 2938 ↛ 2941line 2938 didn't jump to line 2941, because the condition on line 2938 was never false

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

2940 else: 

2941 _data._hardmask = hard_mask 

2942 _data._baseclass = _baseclass 

2943 return _data 

2944 

2945 

2946 def _update_from(self, obj): 

2947 """ 

2948 Copies some attributes of obj to self. 

2949 

2950 """ 

2951 if isinstance(obj, ndarray): 2951 ↛ 2954line 2951 didn't jump to line 2954, because the condition on line 2951 was never false

2952 _baseclass = type(obj) 

2953 else: 

2954 _baseclass = ndarray 

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

2956 _optinfo = {} 

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

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

2959 if not isinstance(obj, MaskedArray): 

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

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

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

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

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

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

2966 _optinfo=_optinfo, 

2967 _basedict=_optinfo) 

2968 self.__dict__.update(_dict) 

2969 self.__dict__.update(_optinfo) 

2970 return 

2971 

2972 def __array_finalize__(self, obj): 

2973 """ 

2974 Finalizes the masked array. 

2975 

2976 """ 

2977 # Get main attributes. 

2978 self._update_from(obj) 

2979 

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2994 # matches the input mask. 

2995 # 

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

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

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

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

3000 # 

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

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

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

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

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

3006 if isinstance(obj, ndarray): 3006 ↛ 3045line 3006 didn't jump to line 3045, because the condition on line 3006 was never false

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

3008 # instead? 

3009 if obj.dtype.names is not None: 3009 ↛ 3010line 3009 didn't jump to line 3010, because the condition on line 3009 was never true

3010 _mask = getmaskarray(obj) 

3011 else: 

3012 _mask = getmask(obj) 

3013 

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

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

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

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

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

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

3020 # side-effecting 'obj' as well. 

3021 if (_mask is not nomask and obj.__array_interface__["data"][0] 3021 ↛ 3028line 3021 didn't jump to line 3028, because the condition on line 3021 was never true

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

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

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

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

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

3027 # needed and use astype instead of copy. 

3028 if self.dtype == obj.dtype: 

3029 _mask_dtype = _mask.dtype 

3030 else: 

3031 _mask_dtype = make_mask_descr(self.dtype) 

3032 

3033 if self.flags.c_contiguous: 

3034 order = "C" 

3035 elif self.flags.f_contiguous: 

3036 order = "F" 

3037 else: 

3038 order = "K" 

3039 

3040 _mask = _mask.astype(_mask_dtype, order) 

3041 else: 

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

3043 _mask = _mask.view() 

3044 else: 

3045 _mask = nomask 

3046 

3047 self._mask = _mask 

3048 # Finalize the mask 

3049 if self._mask is not nomask: 

3050 try: 

3051 self._mask.shape = self.shape 

3052 except ValueError: 

3053 self._mask = nomask 

3054 except (TypeError, AttributeError): 

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

3056 pass 

3057 

3058 # Finalize the fill_value 

3059 if self._fill_value is not None: 3059 ↛ 3060line 3059 didn't jump to line 3060, because the condition on line 3059 was never true

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

3061 elif self.dtype.names is not None: 3061 ↛ 3063line 3061 didn't jump to line 3063, because the condition on line 3061 was never true

3062 # Finalize the default fill_value for structured arrays 

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

3064 

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

3066 """ 

3067 Special hook for ufuncs. 

3068 

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

3070 

3071 """ 

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

3073 result = obj 

3074 else: 

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

3076 result._update_from(self) 

3077 

3078 if context is not None: 

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

3080 func, args, out_i = context 

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

3082 input_args = args[:func.nin] 

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

3084 # Get the domain mask 

3085 domain = ufunc_domain.get(func, None) 

3086 if domain is not None: 

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

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

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

3090 

3091 if d.any(): 

3092 # Fill the result where the domain is wrong 

3093 try: 

3094 # Binary domain: take the last value 

3095 fill_value = ufunc_fills[func][-1] 

3096 except TypeError: 

3097 # Unary domain: just use this one 

3098 fill_value = ufunc_fills[func] 

3099 except KeyError: 

3100 # Domain not recognized, use fill_value instead 

3101 fill_value = self.fill_value 

3102 

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

3104 

3105 # Update the mask 

3106 if m is nomask: 

3107 m = d 

3108 else: 

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

3110 m = (m | d) 

3111 

3112 # Make sure the mask has the proper size 

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

3114 return masked 

3115 else: 

3116 result._mask = m 

3117 result._sharedmask = False 

3118 

3119 return result 

3120 

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

3122 """ 

3123 Return a view of the MaskedArray data. 

3124 

3125 Parameters 

3126 ---------- 

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

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

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

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

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

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

3133 parameter). 

3134 type : Python type, optional 

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

3136 default None results in type preservation. 

3137 fill_value : scalar, optional 

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

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

3140 in its absence the original array, as discussed in the notes below. 

3141 

3142 See Also 

3143 -------- 

3144 numpy.ndarray.view : Equivalent method on ndarray object. 

3145 

3146 Notes 

3147 ----- 

3148 

3149 ``a.view()`` is used two different ways: 

3150 

3151 ``a.view(some_dtype)`` or ``a.view(dtype=some_dtype)`` constructs a view 

3152 of the array's memory with a different data-type. This can cause a 

3153 reinterpretation of the bytes of memory. 

3154 

3155 ``a.view(ndarray_subclass)`` or ``a.view(type=ndarray_subclass)`` just 

3156 returns an instance of `ndarray_subclass` that looks at the same array 

3157 (same shape, dtype, etc.) This does not cause a reinterpretation of the 

3158 memory. 

3159 

3160 If `fill_value` is not specified, but `dtype` is specified (and is not 

3161 an ndarray sub-class), the `fill_value` of the MaskedArray will be 

3162 reset. If neither `fill_value` nor `dtype` are specified (or if 

3163 `dtype` is an ndarray sub-class), then the fill value is preserved. 

3164 Finally, if `fill_value` is specified, but `dtype` is not, the fill 

3165 value is set to the specified value. 

3166 

3167 For ``a.view(some_dtype)``, if ``some_dtype`` has a different number of 

3168 bytes per entry than the previous dtype (for example, converting a 

3169 regular array to a structured array), then the behavior of the view 

3170 cannot be predicted just from the superficial appearance of ``a`` (shown 

3171 by ``print(a)``). It also depends on exactly how ``a`` is stored in 

3172 memory. Therefore if ``a`` is C-ordered versus fortran-ordered, versus 

3173 defined as a slice or transpose, etc., the view may give different 

3174 results. 

3175 """ 

3176 

3177 if dtype is None: 3177 ↛ 3178line 3177 didn't jump to line 3178, because the condition on line 3177 was never true

3178 if type is None: 

3179 output = ndarray.view(self) 

3180 else: 

3181 output = ndarray.view(self, type) 

3182 elif type is None: 3182 ↛ 3192line 3182 didn't jump to line 3192, because the condition on line 3182 was never false

3183 try: 

3184 if issubclass(dtype, ndarray): 3184 ↛ 3188line 3184 didn't jump to line 3188, because the condition on line 3184 was never false

3185 output = ndarray.view(self, dtype) 

3186 dtype = None 

3187 else: 

3188 output = ndarray.view(self, dtype) 

3189 except TypeError: 

3190 output = ndarray.view(self, dtype) 

3191 else: 

3192 output = ndarray.view(self, dtype, type) 

3193 

3194 # also make the mask be a view (so attr changes to the view's 

3195 # mask do no affect original object's mask) 

3196 # (especially important to avoid affecting np.masked singleton) 

3197 if getmask(output) is not nomask: 3197 ↛ 3201line 3197 didn't jump to line 3201, because the condition on line 3197 was never false

3198 output._mask = output._mask.view() 

3199 

3200 # Make sure to reset the _fill_value if needed 

3201 if getattr(output, '_fill_value', None) is not None: 3201 ↛ 3202line 3201 didn't jump to line 3202, because the condition on line 3201 was never true

3202 if fill_value is None: 

3203 if dtype is None: 

3204 pass # leave _fill_value as is 

3205 else: 

3206 output._fill_value = None 

3207 else: 

3208 output.fill_value = fill_value 

3209 return output 

3210 

3211 def __getitem__(self, indx): 

3212 """ 

3213 x.__getitem__(y) <==> x[y] 

3214 

3215 Return the item described by i, as a masked array. 

3216 

3217 """ 

3218 # We could directly use ndarray.__getitem__ on self. 

3219 # But then we would have to modify __array_finalize__ to prevent the 

3220 # mask of being reshaped if it hasn't been set up properly yet 

3221 # So it's easier to stick to the current version 

3222 dout = self.data[indx] 

3223 _mask = self._mask 

3224 

3225 def _is_scalar(m): 

3226 return not isinstance(m, np.ndarray) 

3227 

3228 def _scalar_heuristic(arr, elem): 

3229 """ 

3230 Return whether `elem` is a scalar result of indexing `arr`, or None 

3231 if undecidable without promoting nomask to a full mask 

3232 """ 

3233 # obviously a scalar 

3234 if not isinstance(elem, np.ndarray): 

3235 return True 

3236 

3237 # object array scalar indexing can return anything 

3238 elif arr.dtype.type is np.object_: 

3239 if arr.dtype is not elem.dtype: 

3240 # elem is an array, but dtypes do not match, so must be 

3241 # an element 

3242 return True 

3243 

3244 # well-behaved subclass that only returns 0d arrays when 

3245 # expected - this is not a scalar 

3246 elif type(arr).__getitem__ == ndarray.__getitem__: 

3247 return False 

3248 

3249 return None 

3250 

3251 if _mask is not nomask: 

3252 # _mask cannot be a subclass, so it tells us whether we should 

3253 # expect a scalar. It also cannot be of dtype object. 

3254 mout = _mask[indx] 

3255 scalar_expected = _is_scalar(mout) 

3256 

3257 else: 

3258 # attempt to apply the heuristic to avoid constructing a full mask 

3259 mout = nomask 

3260 scalar_expected = _scalar_heuristic(self.data, dout) 

3261 if scalar_expected is None: 

3262 # heuristics have failed 

3263 # construct a full array, so we can be certain. This is costly. 

3264 # we could also fall back on ndarray.__getitem__(self.data, indx) 

3265 scalar_expected = _is_scalar(getmaskarray(self)[indx]) 

3266 

3267 # Did we extract a single item? 

3268 if scalar_expected: 

3269 # A record 

3270 if isinstance(dout, np.void): 

3271 # We should always re-cast to mvoid, otherwise users can 

3272 # change masks on rows that already have masked values, but not 

3273 # on rows that have no masked values, which is inconsistent. 

3274 return mvoid(dout, mask=mout, hardmask=self._hardmask) 

3275 

3276 # special case introduced in gh-5962 

3277 elif (self.dtype.type is np.object_ and 

3278 isinstance(dout, np.ndarray) and 

3279 dout is not masked): 

3280 # If masked, turn into a MaskedArray, with everything masked. 

3281 if mout: 

3282 return MaskedArray(dout, mask=True) 

3283 else: 

3284 return dout 

3285 

3286 # Just a scalar 

3287 else: 

3288 if mout: 

3289 return masked 

3290 else: 

3291 return dout 

3292 else: 

3293 # Force dout to MA 

3294 dout = dout.view(type(self)) 

3295 # Inherit attributes from self 

3296 dout._update_from(self) 

3297 # Check the fill_value 

3298 if is_string_or_list_of_strings(indx): 

3299 if self._fill_value is not None: 

3300 dout._fill_value = self._fill_value[indx] 

3301 

3302 # Something like gh-15895 has happened if this check fails. 

3303 # _fill_value should always be an ndarray. 

3304 if not isinstance(dout._fill_value, np.ndarray): 

3305 raise RuntimeError('Internal NumPy error.') 

3306 # If we're indexing a multidimensional field in a 

3307 # structured array (such as dtype("(2,)i2,(2,)i1")), 

3308 # dimensionality goes up (M[field].ndim == M.ndim + 

3309 # M.dtype[field].ndim). That's fine for 

3310 # M[field] but problematic for M[field].fill_value 

3311 # which should have shape () to avoid breaking several 

3312 # methods. There is no great way out, so set to 

3313 # first element. See issue #6723. 

3314 if dout._fill_value.ndim > 0: 

3315 if not (dout._fill_value == 

3316 dout._fill_value.flat[0]).all(): 

3317 warnings.warn( 

3318 "Upon accessing multidimensional field " 

3319 f"{indx!s}, need to keep dimensionality " 

3320 "of fill_value at 0. Discarding " 

3321 "heterogeneous fill_value and setting " 

3322 f"all to {dout._fill_value[0]!s}.", 

3323 stacklevel=2) 

3324 # Need to use `.flat[0:1].squeeze(...)` instead of just 

3325 # `.flat[0]` to ensure the result is a 0d array and not 

3326 # a scalar. 

3327 dout._fill_value = dout._fill_value.flat[0:1].squeeze(axis=0) 

3328 dout._isfield = True 

3329 # Update the mask if needed 

3330 if mout is not nomask: 

3331 # set shape to match that of data; this is needed for matrices 

3332 dout._mask = reshape(mout, dout.shape) 

3333 dout._sharedmask = True 

3334 # Note: Don't try to check for m.any(), that'll take too long 

3335 return dout 

3336 

3337 def __setitem__(self, indx, value): 

3338 """ 

3339 x.__setitem__(i, y) <==> x[i]=y 

3340 

3341 Set item described by index. If value is masked, masks those 

3342 locations. 

3343 

3344 """ 

3345 if self is masked: 

3346 raise MaskError('Cannot alter the masked element.') 

3347 _data = self._data 

3348 _mask = self._mask 

3349 if isinstance(indx, str): 

3350 _data[indx] = value 

3351 if _mask is nomask: 

3352 self._mask = _mask = make_mask_none(self.shape, self.dtype) 

3353 _mask[indx] = getmask(value) 

3354 return 

3355 

3356 _dtype = _data.dtype 

3357 

3358 if value is masked: 

3359 # The mask wasn't set: create a full version. 

3360 if _mask is nomask: 

3361 _mask = self._mask = make_mask_none(self.shape, _dtype) 

3362 # Now, set the mask to its value. 

3363 if _dtype.names is not None: 

3364 _mask[indx] = tuple([True] * len(_dtype.names)) 

3365 else: 

3366 _mask[indx] = True 

3367 return 

3368 

3369 # Get the _data part of the new value 

3370 dval = getattr(value, '_data', value) 

3371 # Get the _mask part of the new value 

3372 mval = getmask(value) 

3373 if _dtype.names is not None and mval is nomask: 

3374 mval = tuple([False] * len(_dtype.names)) 

3375 if _mask is nomask: 

3376 # Set the data, then the mask 

3377 _data[indx] = dval 

3378 if mval is not nomask: 

3379 _mask = self._mask = make_mask_none(self.shape, _dtype) 

3380 _mask[indx] = mval 

3381 elif not self._hardmask: 

3382 # Set the data, then the mask 

3383 if (isinstance(indx, masked_array) and 

3384 not isinstance(value, masked_array)): 

3385 _data[indx.data] = dval 

3386 else: 

3387 _data[indx] = dval 

3388 _mask[indx] = mval 

3389 elif hasattr(indx, 'dtype') and (indx.dtype == MaskType): 

3390 indx = indx * umath.logical_not(_mask) 

3391 _data[indx] = dval 

3392 else: 

3393 if _dtype.names is not None: 

3394 err_msg = "Flexible 'hard' masks are not yet supported." 

3395 raise NotImplementedError(err_msg) 

3396 mindx = mask_or(_mask[indx], mval, copy=True) 

3397 dindx = self._data[indx] 

3398 if dindx.size > 1: 

3399 np.copyto(dindx, dval, where=~mindx) 

3400 elif mindx is nomask: 

3401 dindx = dval 

3402 _data[indx] = dindx 

3403 _mask[indx] = mindx 

3404 return 

3405 

3406 # Define so that we can overwrite the setter. 

3407 @property 

3408 def dtype(self): 

3409 return super().dtype 

3410 

3411 @dtype.setter 

3412 def dtype(self, dtype): 

3413 super(MaskedArray, type(self)).dtype.__set__(self, dtype) 

3414 if self._mask is not nomask: 

3415 self._mask = self._mask.view(make_mask_descr(dtype), ndarray) 

3416 # Try to reset the shape of the mask (if we don't have a void). 

3417 # This raises a ValueError if the dtype change won't work. 

3418 try: 

3419 self._mask.shape = self.shape 

3420 except (AttributeError, TypeError): 

3421 pass 

3422 

3423 @property 

3424 def shape(self): 

3425 return super().shape 

3426 

3427 @shape.setter 

3428 def shape(self, shape): 

3429 super(MaskedArray, type(self)).shape.__set__(self, shape) 

3430 # Cannot use self._mask, since it may not (yet) exist when a 

3431 # masked matrix sets the shape. 

3432 if getmask(self) is not nomask: 

3433 self._mask.shape = self.shape 

3434 

3435 def __setmask__(self, mask, copy=False): 

3436 """ 

3437 Set the mask. 

3438 

3439 """ 

3440 idtype = self.dtype 

3441 current_mask = self._mask 

3442 if mask is masked: 

3443 mask = True 

3444 

3445 if current_mask is nomask: 

3446 # Make sure the mask is set 

3447 # Just don't do anything if there's nothing to do. 

3448 if mask is nomask: 

3449 return 

3450 current_mask = self._mask = make_mask_none(self.shape, idtype) 

3451 

3452 if idtype.names is None: 

3453 # No named fields. 

3454 # Hardmask: don't unmask the data 

3455 if self._hardmask: 

3456 current_mask |= mask 

3457 # Softmask: set everything to False 

3458 # If it's obviously a compatible scalar, use a quick update 

3459 # method. 

3460 elif isinstance(mask, (int, float, np.bool_, np.number)): 

3461 current_mask[...] = mask 

3462 # Otherwise fall back to the slower, general purpose way. 

3463 else: 

3464 current_mask.flat = mask 

3465 else: 

3466 # Named fields w/ 

3467 mdtype = current_mask.dtype 

3468 mask = np.array(mask, copy=False) 

3469 # Mask is a singleton 

3470 if not mask.ndim: 

3471 # It's a boolean : make a record 

3472 if mask.dtype.kind == 'b': 

3473 mask = np.array(tuple([mask.item()] * len(mdtype)), 

3474 dtype=mdtype) 

3475 # It's a record: make sure the dtype is correct 

3476 else: 

3477 mask = mask.astype(mdtype) 

3478 # Mask is a sequence 

3479 else: 

3480 # Make sure the new mask is a ndarray with the proper dtype 

3481 try: 

3482 mask = np.array(mask, copy=copy, dtype=mdtype) 

3483 # Or assume it's a sequence of bool/int 

3484 except TypeError: 

3485 mask = np.array([tuple([m] * len(mdtype)) for m in mask], 

3486 dtype=mdtype) 

3487 # Hardmask: don't unmask the data 

3488 if self._hardmask: 

3489 for n in idtype.names: 

3490 current_mask[n] |= mask[n] 

3491 # Softmask: set everything to False 

3492 # If it's obviously a compatible scalar, use a quick update 

3493 # method. 

3494 elif isinstance(mask, (int, float, np.bool_, np.number)): 

3495 current_mask[...] = mask 

3496 # Otherwise fall back to the slower, general purpose way. 

3497 else: 

3498 current_mask.flat = mask 

3499 # Reshape if needed 

3500 if current_mask.shape: 

3501 current_mask.shape = self.shape 

3502 return 

3503 

3504 _set_mask = __setmask__ 

3505 

3506 @property 

3507 def mask(self): 

3508 """ Current mask. """ 

3509 

3510 # We could try to force a reshape, but that wouldn't work in some 

3511 # cases. 

3512 # Return a view so that the dtype and shape cannot be changed in place 

3513 # This still preserves nomask by identity 

3514 return self._mask.view() 

3515 

3516 @mask.setter 

3517 def mask(self, value): 

3518 self.__setmask__(value) 

3519 

3520 @property 

3521 def recordmask(self): 

3522 """ 

3523 Get or set the mask of the array if it has no named fields. For 

3524 structured arrays, returns a ndarray of booleans where entries are 

3525 ``True`` if **all** the fields are masked, ``False`` otherwise: 

3526 

3527 >>> x = np.ma.array([(1, 1), (2, 2), (3, 3), (4, 4), (5, 5)], 

3528 ... mask=[(0, 0), (1, 0), (1, 1), (0, 1), (0, 0)], 

3529 ... dtype=[('a', int), ('b', int)]) 

3530 >>> x.recordmask 

3531 array([False, False, True, False, False]) 

3532 """ 

3533 

3534 _mask = self._mask.view(ndarray) 

3535 if _mask.dtype.names is None: 

3536 return _mask 

3537 return np.all(flatten_structured_array(_mask), axis=-1) 

3538 

3539 @recordmask.setter 

3540 def recordmask(self, mask): 

3541 raise NotImplementedError("Coming soon: setting the mask per records!") 

3542 

3543 def harden_mask(self): 

3544 """ 

3545 Force the mask to hard, preventing unmasking by assignment. 

3546 

3547 Whether the mask of a masked array is hard or soft is determined by 

3548 its `~ma.MaskedArray.hardmask` property. `harden_mask` sets 

3549 `~ma.MaskedArray.hardmask` to ``True`` (and returns the modified 

3550 self). 

3551 

3552 See Also 

3553 -------- 

3554 ma.MaskedArray.hardmask 

3555 ma.MaskedArray.soften_mask 

3556 

3557 """ 

3558 self._hardmask = True 

3559 return self 

3560 

3561 def soften_mask(self): 

3562 """ 

3563 Force the mask to soft (default), allowing unmasking by assignment. 

3564 

3565 Whether the mask of a masked array is hard or soft is determined by 

3566 its `~ma.MaskedArray.hardmask` property. `soften_mask` sets 

3567 `~ma.MaskedArray.hardmask` to ``False`` (and returns the modified 

3568 self). 

3569 

3570 See Also 

3571 -------- 

3572 ma.MaskedArray.hardmask 

3573 ma.MaskedArray.harden_mask 

3574 

3575 """ 

3576 self._hardmask = False 

3577 return self 

3578 

3579 @property 

3580 def hardmask(self): 

3581 """ 

3582 Specifies whether values can be unmasked through assignments. 

3583 

3584 By default, assigning definite values to masked array entries will 

3585 unmask them. When `hardmask` is ``True``, the mask will not change 

3586 through assignments. 

3587 

3588 See Also 

3589 -------- 

3590 ma.MaskedArray.harden_mask 

3591 ma.MaskedArray.soften_mask 

3592 

3593 Examples 

3594 -------- 

3595 >>> x = np.arange(10) 

3596 >>> m = np.ma.masked_array(x, x>5) 

3597 >>> assert not m.hardmask 

3598 

3599 Since `m` has a soft mask, assigning an element value unmasks that 

3600 element: 

3601 

3602 >>> m[8] = 42 

3603 >>> m 

3604 masked_array(data=[0, 1, 2, 3, 4, 5, --, --, 42, --], 

3605 mask=[False, False, False, False, False, False, 

3606 True, True, False, True], 

3607 fill_value=999999) 

3608 

3609 After hardening, the mask is not affected by assignments: 

3610 

3611 >>> hardened = np.ma.harden_mask(m) 

3612 >>> assert m.hardmask and hardened is m 

3613 >>> m[:] = 23 

3614 >>> m 

3615 masked_array(data=[23, 23, 23, 23, 23, 23, --, --, 23, --], 

3616 mask=[False, False, False, False, False, False, 

3617 True, True, False, True], 

3618 fill_value=999999) 

3619 

3620 """ 

3621 return self._hardmask 

3622 

3623 def unshare_mask(self): 

3624 """ 

3625 Copy the mask and set the `sharedmask` flag to ``False``. 

3626 

3627 Whether the mask is shared between masked arrays can be seen from 

3628 the `sharedmask` property. `unshare_mask` ensures the mask is not 

3629 shared. A copy of the mask is only made if it was shared. 

3630 

3631 See Also 

3632 -------- 

3633 sharedmask 

3634 

3635 """ 

3636 if self._sharedmask: 

3637 self._mask = self._mask.copy() 

3638 self._sharedmask = False 

3639 return self 

3640 

3641 @property 

3642 def sharedmask(self): 

3643 """ Share status of the mask (read-only). """ 

3644 return self._sharedmask 

3645 

3646 def shrink_mask(self): 

3647 """ 

3648 Reduce a mask to nomask when possible. 

3649 

3650 Parameters 

3651 ---------- 

3652 None 

3653 

3654 Returns 

3655 ------- 

3656 None 

3657 

3658 Examples 

3659 -------- 

3660 >>> x = np.ma.array([[1,2 ], [3, 4]], mask=[0]*4) 

3661 >>> x.mask 

3662 array([[False, False], 

3663 [False, False]]) 

3664 >>> x.shrink_mask() 

3665 masked_array( 

3666 data=[[1, 2], 

3667 [3, 4]], 

3668 mask=False, 

3669 fill_value=999999) 

3670 >>> x.mask 

3671 False 

3672 

3673 """ 

3674 self._mask = _shrink_mask(self._mask) 

3675 return self 

3676 

3677 @property 

3678 def baseclass(self): 

3679 """ Class of the underlying data (read-only). """ 

3680 return self._baseclass 

3681 

3682 def _get_data(self): 

3683 """ 

3684 Returns the underlying data, as a view of the masked array. 

3685 

3686 If the underlying data is a subclass of :class:`numpy.ndarray`, it is 

3687 returned as such. 

3688 

3689 >>> x = np.ma.array(np.matrix([[1, 2], [3, 4]]), mask=[[0, 1], [1, 0]]) 

3690 >>> x.data 

3691 matrix([[1, 2], 

3692 [3, 4]]) 

3693 

3694 The type of the data can be accessed through the :attr:`baseclass` 

3695 attribute. 

3696 """ 

3697 return ndarray.view(self, self._baseclass) 

3698 

3699 _data = property(fget=_get_data) 

3700 data = property(fget=_get_data) 

3701 

3702 @property 

3703 def flat(self): 

3704 """ Return a flat iterator, or set a flattened version of self to value. """ 

3705 return MaskedIterator(self) 

3706 

3707 @flat.setter 

3708 def flat(self, value): 

3709 y = self.ravel() 

3710 y[:] = value 

3711 

3712 @property 

3713 def fill_value(self): 

3714 """ 

3715 The filling value of the masked array is a scalar. When setting, None 

3716 will set to a default based on the data type. 

3717 

3718 Examples 

3719 -------- 

3720 >>> for dt in [np.int32, np.int64, np.float64, np.complex128]: 

3721 ... np.ma.array([0, 1], dtype=dt).get_fill_value() 

3722 ... 

3723 999999 

3724 999999 

3725 1e+20 

3726 (1e+20+0j) 

3727 

3728 >>> x = np.ma.array([0, 1.], fill_value=-np.inf) 

3729 >>> x.fill_value 

3730 -inf 

3731 >>> x.fill_value = np.pi 

3732 >>> x.fill_value 

3733 3.1415926535897931 # may vary 

3734 

3735 Reset to default: 

3736 

3737 >>> x.fill_value = None 

3738 >>> x.fill_value 

3739 1e+20 

3740 

3741 """ 

3742 if self._fill_value is None: 

3743 self._fill_value = _check_fill_value(None, self.dtype) 

3744 

3745 # Temporary workaround to account for the fact that str and bytes 

3746 # scalars cannot be indexed with (), whereas all other numpy 

3747 # scalars can. See issues #7259 and #7267. 

3748 # The if-block can be removed after #7267 has been fixed. 

3749 if isinstance(self._fill_value, ndarray): 

3750 return self._fill_value[()] 

3751 return self._fill_value 

3752 

3753 @fill_value.setter 

3754 def fill_value(self, value=None): 

3755 target = _check_fill_value(value, self.dtype) 

3756 if not target.ndim == 0: 

3757 # 2019-11-12, 1.18.0 

3758 warnings.warn( 

3759 "Non-scalar arrays for the fill value are deprecated. Use " 

3760 "arrays with scalar values instead. The filled function " 

3761 "still supports any array as `fill_value`.", 

3762 DeprecationWarning, stacklevel=2) 

3763 

3764 _fill_value = self._fill_value 

3765 if _fill_value is None: 

3766 # Create the attribute if it was undefined 

3767 self._fill_value = target 

3768 else: 

3769 # Don't overwrite the attribute, just fill it (for propagation) 

3770 _fill_value[()] = target 

3771 

3772 # kept for compatibility 

3773 get_fill_value = fill_value.fget 

3774 set_fill_value = fill_value.fset 

3775 

3776 def filled(self, fill_value=None): 

3777 """ 

3778 Return a copy of self, with masked values filled with a given value. 

3779 **However**, if there are no masked values to fill, self will be 

3780 returned instead as an ndarray. 

3781 

3782 Parameters 

3783 ---------- 

3784 fill_value : array_like, optional 

3785 The value to use for invalid entries. Can be scalar or non-scalar. 

3786 If non-scalar, the resulting ndarray must be broadcastable over 

3787 input array. Default is None, in which case, the `fill_value` 

3788 attribute of the array is used instead. 

3789 

3790 Returns 

3791 ------- 

3792 filled_array : ndarray 

3793 A copy of ``self`` with invalid entries replaced by *fill_value* 

3794 (be it the function argument or the attribute of ``self``), or 

3795 ``self`` itself as an ndarray if there are no invalid entries to 

3796 be replaced. 

3797 

3798 Notes 

3799 ----- 

3800 The result is **not** a MaskedArray! 

3801 

3802 Examples 

3803 -------- 

3804 >>> x = np.ma.array([1,2,3,4,5], mask=[0,0,1,0,1], fill_value=-999) 

3805 >>> x.filled() 

3806 array([ 1, 2, -999, 4, -999]) 

3807 >>> x.filled(fill_value=1000) 

3808 array([ 1, 2, 1000, 4, 1000]) 

3809 >>> type(x.filled()) 

3810 <class 'numpy.ndarray'> 

3811 

3812 Subclassing is preserved. This means that if, e.g., the data part of 

3813 the masked array is a recarray, `filled` returns a recarray: 

3814 

3815 >>> x = np.array([(-1, 2), (-3, 4)], dtype='i8,i8').view(np.recarray) 

3816 >>> m = np.ma.array(x, mask=[(True, False), (False, True)]) 

3817 >>> m.filled() 

3818 rec.array([(999999, 2), ( -3, 999999)], 

3819 dtype=[('f0', '<i8'), ('f1', '<i8')]) 

3820 """ 

3821 m = self._mask 

3822 if m is nomask: 

3823 return self._data 

3824 

3825 if fill_value is None: 

3826 fill_value = self.fill_value 

3827 else: 

3828 fill_value = _check_fill_value(fill_value, self.dtype) 

3829 

3830 if self is masked_singleton: 

3831 return np.asanyarray(fill_value) 

3832 

3833 if m.dtype.names is not None: 

3834 result = self._data.copy('K') 

3835 _recursive_filled(result, self._mask, fill_value) 

3836 elif not m.any(): 

3837 return self._data 

3838 else: 

3839 result = self._data.copy('K') 

3840 try: 

3841 np.copyto(result, fill_value, where=m) 

3842 except (TypeError, AttributeError): 

3843 fill_value = narray(fill_value, dtype=object) 

3844 d = result.astype(object) 

3845 result = np.choose(m, (d, fill_value)) 

3846 except IndexError: 

3847 # ok, if scalar 

3848 if self._data.shape: 

3849 raise 

3850 elif m: 

3851 result = np.array(fill_value, dtype=self.dtype) 

3852 else: 

3853 result = self._data 

3854 return result 

3855 

3856 def compressed(self): 

3857 """ 

3858 Return all the non-masked data as a 1-D array. 

3859 

3860 Returns 

3861 ------- 

3862 data : ndarray 

3863 A new `ndarray` holding the non-masked data is returned. 

3864 

3865 Notes 

3866 ----- 

3867 The result is **not** a MaskedArray! 

3868 

3869 Examples 

3870 -------- 

3871 >>> x = np.ma.array(np.arange(5), mask=[0]*2 + [1]*3) 

3872 >>> x.compressed() 

3873 array([0, 1]) 

3874 >>> type(x.compressed()) 

3875 <class 'numpy.ndarray'> 

3876 

3877 """ 

3878 data = ndarray.ravel(self._data) 

3879 if self._mask is not nomask: 

3880 data = data.compress(np.logical_not(ndarray.ravel(self._mask))) 

3881 return data 

3882 

3883 def compress(self, condition, axis=None, out=None): 

3884 """ 

3885 Return `a` where condition is ``True``. 

3886 

3887 If condition is a `~ma.MaskedArray`, missing values are considered 

3888 as ``False``. 

3889 

3890 Parameters 

3891 ---------- 

3892 condition : var 

3893 Boolean 1-d array selecting which entries to return. If len(condition) 

3894 is less than the size of a along the axis, then output is truncated 

3895 to length of condition array. 

3896 axis : {None, int}, optional 

3897 Axis along which the operation must be performed. 

3898 out : {None, ndarray}, optional 

3899 Alternative output array in which to place the result. It must have 

3900 the same shape as the expected output but the type will be cast if 

3901 necessary. 

3902 

3903 Returns 

3904 ------- 

3905 result : MaskedArray 

3906 A :class:`~ma.MaskedArray` object. 

3907 

3908 Notes 

3909 ----- 

3910 Please note the difference with :meth:`compressed` ! 

3911 The output of :meth:`compress` has a mask, the output of 

3912 :meth:`compressed` does not. 

3913 

3914 Examples 

3915 -------- 

3916 >>> x = np.ma.array([[1,2,3],[4,5,6],[7,8,9]], mask=[0] + [1,0]*4) 

3917 >>> x 

3918 masked_array( 

3919 data=[[1, --, 3], 

3920 [--, 5, --], 

3921 [7, --, 9]], 

3922 mask=[[False, True, False], 

3923 [ True, False, True], 

3924 [False, True, False]], 

3925 fill_value=999999) 

3926 >>> x.compress([1, 0, 1]) 

3927 masked_array(data=[1, 3], 

3928 mask=[False, False], 

3929 fill_value=999999) 

3930 

3931 >>> x.compress([1, 0, 1], axis=1) 

3932 masked_array( 

3933 data=[[1, 3], 

3934 [--, --], 

3935 [7, 9]], 

3936 mask=[[False, False], 

3937 [ True, True], 

3938 [False, False]], 

3939 fill_value=999999) 

3940 

3941 """ 

3942 # Get the basic components 

3943 (_data, _mask) = (self._data, self._mask) 

3944 

3945 # Force the condition to a regular ndarray and forget the missing 

3946 # values. 

3947 condition = np.asarray(condition) 

3948 

3949 _new = _data.compress(condition, axis=axis, out=out).view(type(self)) 

3950 _new._update_from(self) 

3951 if _mask is not nomask: 

3952 _new._mask = _mask.compress(condition, axis=axis) 

3953 return _new 

3954 

3955 def _insert_masked_print(self): 

3956 """ 

3957 Replace masked values with masked_print_option, casting all innermost 

3958 dtypes to object. 

3959 """ 

3960 if masked_print_option.enabled(): 

3961 mask = self._mask 

3962 if mask is nomask: 

3963 res = self._data 

3964 else: 

3965 # convert to object array to make filled work 

3966 data = self._data 

3967 # For big arrays, to avoid a costly conversion to the 

3968 # object dtype, extract the corners before the conversion. 

3969 print_width = (self._print_width if self.ndim > 1 

3970 else self._print_width_1d) 

3971 for axis in range(self.ndim): 

3972 if data.shape[axis] > print_width: 

3973 ind = print_width // 2 

3974 arr = np.split(data, (ind, -ind), axis=axis) 

3975 data = np.concatenate((arr[0], arr[2]), axis=axis) 

3976 arr = np.split(mask, (ind, -ind), axis=axis) 

3977 mask = np.concatenate((arr[0], arr[2]), axis=axis) 

3978 

3979 rdtype = _replace_dtype_fields(self.dtype, "O") 

3980 res = data.astype(rdtype) 

3981 _recursive_printoption(res, mask, masked_print_option) 

3982 else: 

3983 res = self.filled(self.fill_value) 

3984 return res 

3985 

3986 def __str__(self): 

3987 return str(self._insert_masked_print()) 

3988 

3989 def __repr__(self): 

3990 """ 

3991 Literal string representation. 

3992 

3993 """ 

3994 if self._baseclass is np.ndarray: 

3995 name = 'array' 

3996 else: 

3997 name = self._baseclass.__name__ 

3998 

3999 

4000 # 2016-11-19: Demoted to legacy format 

4001 if np.core.arrayprint._get_legacy_print_mode() <= 113: 

4002 is_long = self.ndim > 1 

4003 parameters = dict( 

4004 name=name, 

4005 nlen=" " * len(name), 

4006 data=str(self), 

4007 mask=str(self._mask), 

4008 fill=str(self.fill_value), 

4009 dtype=str(self.dtype) 

4010 ) 

4011 is_structured = bool(self.dtype.names) 

4012 key = '{}_{}'.format( 

4013 'long' if is_long else 'short', 

4014 'flx' if is_structured else 'std' 

4015 ) 

4016 return _legacy_print_templates[key] % parameters 

4017 

4018 prefix = f"masked_{name}(" 

4019 

4020 dtype_needed = ( 

4021 not np.core.arrayprint.dtype_is_implied(self.dtype) or 

4022 np.all(self.mask) or 

4023 self.size == 0 

4024 ) 

4025 

4026 # determine which keyword args need to be shown 

4027 keys = ['data', 'mask', 'fill_value'] 

4028 if dtype_needed: 

4029 keys.append('dtype') 

4030 

4031 # array has only one row (non-column) 

4032 is_one_row = builtins.all(dim == 1 for dim in self.shape[:-1]) 

4033 

4034 # choose what to indent each keyword with 

4035 min_indent = 2 

4036 if is_one_row: 

4037 # first key on the same line as the type, remaining keys 

4038 # aligned by equals 

4039 indents = {} 

4040 indents[keys[0]] = prefix 

4041 for k in keys[1:]: 

4042 n = builtins.max(min_indent, len(prefix + keys[0]) - len(k)) 

4043 indents[k] = ' ' * n 

4044 prefix = '' # absorbed into the first indent 

4045 else: 

4046 # each key on its own line, indented by two spaces 

4047 indents = {k: ' ' * min_indent for k in keys} 

4048 prefix = prefix + '\n' # first key on the next line 

4049 

4050 # format the field values 

4051 reprs = {} 

4052 reprs['data'] = np.array2string( 

4053 self._insert_masked_print(), 

4054 separator=", ", 

4055 prefix=indents['data'] + 'data=', 

4056 suffix=',') 

4057 reprs['mask'] = np.array2string( 

4058 self._mask, 

4059 separator=", ", 

4060 prefix=indents['mask'] + 'mask=', 

4061 suffix=',') 

4062 reprs['fill_value'] = repr(self.fill_value) 

4063 if dtype_needed: 

4064 reprs['dtype'] = np.core.arrayprint.dtype_short_repr(self.dtype) 

4065 

4066 # join keys with values and indentations 

4067 result = ',\n'.join( 

4068 '{}{}={}'.format(indents[k], k, reprs[k]) 

4069 for k in keys 

4070 ) 

4071 return prefix + result + ')' 

4072 

4073 def _delegate_binop(self, other): 

4074 # This emulates the logic in 

4075 # private/binop_override.h:forward_binop_should_defer 

4076 if isinstance(other, type(self)): 

4077 return False 

4078 array_ufunc = getattr(other, "__array_ufunc__", False) 

4079 if array_ufunc is False: 

4080 other_priority = getattr(other, "__array_priority__", -1000000) 

4081 return self.__array_priority__ < other_priority 

4082 else: 

4083 # If array_ufunc is not None, it will be called inside the ufunc; 

4084 # None explicitly tells us to not call the ufunc, i.e., defer. 

4085 return array_ufunc is None 

4086 

4087 def _comparison(self, other, compare): 

4088 """Compare self with other using operator.eq or operator.ne. 

4089 

4090 When either of the elements is masked, the result is masked as well, 

4091 but the underlying boolean data are still set, with self and other 

4092 considered equal if both are masked, and unequal otherwise. 

4093 

4094 For structured arrays, all fields are combined, with masked values 

4095 ignored. The result is masked if all fields were masked, with self 

4096 and other considered equal only if both were fully masked. 

4097 """ 

4098 omask = getmask(other) 

4099 smask = self.mask 

4100 mask = mask_or(smask, omask, copy=True) 

4101 

4102 odata = getdata(other) 

4103 if mask.dtype.names is not None: 

4104 # For possibly masked structured arrays we need to be careful, 

4105 # since the standard structured array comparison will use all 

4106 # fields, masked or not. To avoid masked fields influencing the 

4107 # outcome, we set all masked fields in self to other, so they'll 

4108 # count as equal. To prepare, we ensure we have the right shape. 

4109 broadcast_shape = np.broadcast(self, odata).shape 

4110 sbroadcast = np.broadcast_to(self, broadcast_shape, subok=True) 

4111 sbroadcast._mask = mask 

4112 sdata = sbroadcast.filled(odata) 

4113 # Now take care of the mask; the merged mask should have an item 

4114 # masked if all fields were masked (in one and/or other). 

4115 mask = (mask == np.ones((), mask.dtype)) 

4116 

4117 else: 

4118 # For regular arrays, just use the data as they come. 

4119 sdata = self.data 

4120 

4121 check = compare(sdata, odata) 

4122 

4123 if isinstance(check, (np.bool_, bool)): 

4124 return masked if mask else check 

4125 

4126 if mask is not nomask: 

4127 # Adjust elements that were masked, which should be treated 

4128 # as equal if masked in both, unequal if masked in one. 

4129 # Note that this works automatically for structured arrays too. 

4130 check = np.where(mask, compare(smask, omask), check) 

4131 if mask.shape != check.shape: 

4132 # Guarantee consistency of the shape, making a copy since the 

4133 # the mask may need to get written to later. 

4134 mask = np.broadcast_to(mask, check.shape).copy() 

4135 

4136 check = check.view(type(self)) 

4137 check._update_from(self) 

4138 check._mask = mask 

4139 

4140 # Cast fill value to bool_ if needed. If it cannot be cast, the 

4141 # default boolean fill value is used. 

4142 if check._fill_value is not None: 

4143 try: 

4144 fill = _check_fill_value(check._fill_value, np.bool_) 

4145 except (TypeError, ValueError): 

4146 fill = _check_fill_value(None, np.bool_) 

4147 check._fill_value = fill 

4148 

4149 return check 

4150 

4151 def __eq__(self, other): 

4152 """Check whether other equals self elementwise. 

4153 

4154 When either of the elements is masked, the result is masked as well, 

4155 but the underlying boolean data are still set, with self and other 

4156 considered equal if both are masked, and unequal otherwise. 

4157 

4158 For structured arrays, all fields are combined, with masked values 

4159 ignored. The result is masked if all fields were masked, with self 

4160 and other considered equal only if both were fully masked. 

4161 """ 

4162 return self._comparison(other, operator.eq) 

4163 

4164 def __ne__(self, other): 

4165 """Check whether other does not equal self elementwise. 

4166 

4167 When either of the elements is masked, the result is masked as well, 

4168 but the underlying boolean data are still set, with self and other 

4169 considered equal if both are masked, and unequal otherwise. 

4170 

4171 For structured arrays, all fields are combined, with masked values 

4172 ignored. The result is masked if all fields were masked, with self 

4173 and other considered equal only if both were fully masked. 

4174 """ 

4175 return self._comparison(other, operator.ne) 

4176 

4177 def __add__(self, other): 

4178 """ 

4179 Add self to other, and return a new masked array. 

4180 

4181 """ 

4182 if self._delegate_binop(other): 

4183 return NotImplemented 

4184 return add(self, other) 

4185 

4186 def __radd__(self, other): 

4187 """ 

4188 Add other to self, and return a new masked array. 

4189 

4190 """ 

4191 # In analogy with __rsub__ and __rdiv__, use original order: 

4192 # we get here from `other + self`. 

4193 return add(other, self) 

4194 

4195 def __sub__(self, other): 

4196 """ 

4197 Subtract other from self, and return a new masked array. 

4198 

4199 """ 

4200 if self._delegate_binop(other): 

4201 return NotImplemented 

4202 return subtract(self, other) 

4203 

4204 def __rsub__(self, other): 

4205 """ 

4206 Subtract self from other, and return a new masked array. 

4207 

4208 """ 

4209 return subtract(other, self) 

4210 

4211 def __mul__(self, other): 

4212 "Multiply self by other, and return a new masked array." 

4213 if self._delegate_binop(other): 

4214 return NotImplemented 

4215 return multiply(self, other) 

4216 

4217 def __rmul__(self, other): 

4218 """ 

4219 Multiply other by self, and return a new masked array. 

4220 

4221 """ 

4222 # In analogy with __rsub__ and __rdiv__, use original order: 

4223 # we get here from `other * self`. 

4224 return multiply(other, self) 

4225 

4226 def __div__(self, other): 

4227 """ 

4228 Divide other into self, and return a new masked array. 

4229 

4230 """ 

4231 if self._delegate_binop(other): 

4232 return NotImplemented 

4233 return divide(self, other) 

4234 

4235 def __truediv__(self, other): 

4236 """ 

4237 Divide other into self, and return a new masked array. 

4238 

4239 """ 

4240 if self._delegate_binop(other): 

4241 return NotImplemented 

4242 return true_divide(self, other) 

4243 

4244 def __rtruediv__(self, other): 

4245 """ 

4246 Divide self into other, and return a new masked array. 

4247 

4248 """ 

4249 return true_divide(other, self) 

4250 

4251 def __floordiv__(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 floor_divide(self, other) 

4259 

4260 def __rfloordiv__(self, other): 

4261 """ 

4262 Divide self into other, and return a new masked array. 

4263 

4264 """ 

4265 return floor_divide(other, self) 

4266 

4267 def __pow__(self, other): 

4268 """ 

4269 Raise self to the power other, masking the potential NaNs/Infs 

4270 

4271 """ 

4272 if self._delegate_binop(other): 

4273 return NotImplemented 

4274 return power(self, other) 

4275 

4276 def __rpow__(self, other): 

4277 """ 

4278 Raise other to the power self, masking the potential NaNs/Infs 

4279 

4280 """ 

4281 return power(other, self) 

4282 

4283 def __iadd__(self, other): 

4284 """ 

4285 Add other to self in-place. 

4286 

4287 """ 

4288 m = getmask(other) 

4289 if self._mask is nomask: 

4290 if m is not nomask and m.any(): 

4291 self._mask = make_mask_none(self.shape, self.dtype) 

4292 self._mask += m 

4293 else: 

4294 if m is not nomask: 

4295 self._mask += m 

4296 self._data.__iadd__(np.where(self._mask, self.dtype.type(0), 

4297 getdata(other))) 

4298 return self 

4299 

4300 def __isub__(self, other): 

4301 """ 

4302 Subtract other from self in-place. 

4303 

4304 """ 

4305 m = getmask(other) 

4306 if self._mask is nomask: 

4307 if m is not nomask and m.any(): 

4308 self._mask = make_mask_none(self.shape, self.dtype) 

4309 self._mask += m 

4310 elif m is not nomask: 

4311 self._mask += m 

4312 self._data.__isub__(np.where(self._mask, self.dtype.type(0), 

4313 getdata(other))) 

4314 return self 

4315 

4316 def __imul__(self, other): 

4317 """ 

4318 Multiply self by other in-place. 

4319 

4320 """ 

4321 m = getmask(other) 

4322 if self._mask is nomask: 

4323 if m is not nomask and m.any(): 

4324 self._mask = make_mask_none(self.shape, self.dtype) 

4325 self._mask += m 

4326 elif m is not nomask: 

4327 self._mask += m 

4328 self._data.__imul__(np.where(self._mask, self.dtype.type(1), 

4329 getdata(other))) 

4330 return self 

4331 

4332 def __idiv__(self, other): 

4333 """ 

4334 Divide self by other in-place. 

4335 

4336 """ 

4337 other_data = getdata(other) 

4338 dom_mask = _DomainSafeDivide().__call__(self._data, other_data) 

4339 other_mask = getmask(other) 

4340 new_mask = mask_or(other_mask, dom_mask) 

4341 # The following 3 lines control the domain filling 

4342 if dom_mask.any(): 

4343 (_, fval) = ufunc_fills[np.divide] 

4344 other_data = np.where(dom_mask, fval, other_data) 

4345 self._mask |= new_mask 

4346 self._data.__idiv__(np.where(self._mask, self.dtype.type(1), 

4347 other_data)) 

4348 return self 

4349 

4350 def __ifloordiv__(self, other): 

4351 """ 

4352 Floor divide self by other in-place. 

4353 

4354 """ 

4355 other_data = getdata(other) 

4356 dom_mask = _DomainSafeDivide().__call__(self._data, other_data) 

4357 other_mask = getmask(other) 

4358 new_mask = mask_or(other_mask, dom_mask) 

4359 # The following 3 lines control the domain filling 

4360 if dom_mask.any(): 

4361 (_, fval) = ufunc_fills[np.floor_divide] 

4362 other_data = np.where(dom_mask, fval, other_data) 

4363 self._mask |= new_mask 

4364 self._data.__ifloordiv__(np.where(self._mask, self.dtype.type(1), 

4365 other_data)) 

4366 return self 

4367 

4368 def __itruediv__(self, other): 

4369 """ 

4370 True divide self by other in-place. 

4371 

4372 """ 

4373 other_data = getdata(other) 

4374 dom_mask = _DomainSafeDivide().__call__(self._data, other_data) 

4375 other_mask = getmask(other) 

4376 new_mask = mask_or(other_mask, dom_mask) 

4377 # The following 3 lines control the domain filling 

4378 if dom_mask.any(): 

4379 (_, fval) = ufunc_fills[np.true_divide] 

4380 other_data = np.where(dom_mask, fval, other_data) 

4381 self._mask |= new_mask 

4382 self._data.__itruediv__(np.where(self._mask, self.dtype.type(1), 

4383 other_data)) 

4384 return self 

4385 

4386 def __ipow__(self, other): 

4387 """ 

4388 Raise self to the power other, in place. 

4389 

4390 """ 

4391 other_data = getdata(other) 

4392 other_mask = getmask(other) 

4393 with np.errstate(divide='ignore', invalid='ignore'): 

4394 self._data.__ipow__(np.where(self._mask, self.dtype.type(1), 

4395 other_data)) 

4396 invalid = np.logical_not(np.isfinite(self._data)) 

4397 if invalid.any(): 

4398 if self._mask is not nomask: 

4399 self._mask |= invalid 

4400 else: 

4401 self._mask = invalid 

4402 np.copyto(self._data, self.fill_value, where=invalid) 

4403 new_mask = mask_or(other_mask, invalid) 

4404 self._mask = mask_or(self._mask, new_mask) 

4405 return self 

4406 

4407 def __float__(self): 

4408 """ 

4409 Convert to float. 

4410 

4411 """ 

4412 if self.size > 1: 

4413 raise TypeError("Only length-1 arrays can be converted " 

4414 "to Python scalars") 

4415 elif self._mask: 

4416 warnings.warn("Warning: converting a masked element to nan.", stacklevel=2) 

4417 return np.nan 

4418 return float(self.item()) 

4419 

4420 def __int__(self): 

4421 """ 

4422 Convert to int. 

4423 

4424 """ 

4425 if self.size > 1: 

4426 raise TypeError("Only length-1 arrays can be converted " 

4427 "to Python scalars") 

4428 elif self._mask: 

4429 raise MaskError('Cannot convert masked element to a Python int.') 

4430 return int(self.item()) 

4431 

4432 @property 

4433 def imag(self): 

4434 """ 

4435 The imaginary part of the masked array. 

4436 

4437 This property is a view on the imaginary part of this `MaskedArray`. 

4438 

4439 See Also 

4440 -------- 

4441 real 

4442 

4443 Examples 

4444 -------- 

4445 >>> x = np.ma.array([1+1.j, -2j, 3.45+1.6j], mask=[False, True, False]) 

4446 >>> x.imag 

4447 masked_array(data=[1.0, --, 1.6], 

4448 mask=[False, True, False], 

4449 fill_value=1e+20) 

4450 

4451 """ 

4452 result = self._data.imag.view(type(self)) 

4453 result.__setmask__(self._mask) 

4454 return result 

4455 

4456 # kept for compatibility 

4457 get_imag = imag.fget 

4458 

4459 @property 

4460 def real(self): 

4461 """ 

4462 The real part of the masked array. 

4463 

4464 This property is a view on the real part of this `MaskedArray`. 

4465 

4466 See Also 

4467 -------- 

4468 imag 

4469 

4470 Examples 

4471 -------- 

4472 >>> x = np.ma.array([1+1.j, -2j, 3.45+1.6j], mask=[False, True, False]) 

4473 >>> x.real 

4474 masked_array(data=[1.0, --, 3.45], 

4475 mask=[False, True, False], 

4476 fill_value=1e+20) 

4477 

4478 """ 

4479 result = self._data.real.view(type(self)) 

4480 result.__setmask__(self._mask) 

4481 return result 

4482 

4483 # kept for compatibility 

4484 get_real = real.fget 

4485 

4486 def count(self, axis=None, keepdims=np._NoValue): 

4487 """ 

4488 Count the non-masked elements of the array along the given axis. 

4489 

4490 Parameters 

4491 ---------- 

4492 axis : None or int or tuple of ints, optional 

4493 Axis or axes along which the count is performed. 

4494 The default, None, performs the count over all 

4495 the dimensions of the input array. `axis` may be negative, in 

4496 which case it counts from the last to the first axis. 

4497 

4498 .. versionadded:: 1.10.0 

4499 

4500 If this is a tuple of ints, the count is performed on multiple 

4501 axes, instead of a single axis or all the axes as before. 

4502 keepdims : bool, optional 

4503 If this is set to True, the axes which are reduced are left 

4504 in the result as dimensions with size one. With this option, 

4505 the result will broadcast correctly against the array. 

4506 

4507 Returns 

4508 ------- 

4509 result : ndarray or scalar 

4510 An array with the same shape as the input array, with the specified 

4511 axis removed. If the array is a 0-d array, or if `axis` is None, a 

4512 scalar is returned. 

4513 

4514 See Also 

4515 -------- 

4516 ma.count_masked : Count masked elements in array or along a given axis. 

4517 

4518 Examples 

4519 -------- 

4520 >>> import numpy.ma as ma 

4521 >>> a = ma.arange(6).reshape((2, 3)) 

4522 >>> a[1, :] = ma.masked 

4523 >>> a 

4524 masked_array( 

4525 data=[[0, 1, 2], 

4526 [--, --, --]], 

4527 mask=[[False, False, False], 

4528 [ True, True, True]], 

4529 fill_value=999999) 

4530 >>> a.count() 

4531 3 

4532 

4533 When the `axis` keyword is specified an array of appropriate size is 

4534 returned. 

4535 

4536 >>> a.count(axis=0) 

4537 array([1, 1, 1]) 

4538 >>> a.count(axis=1) 

4539 array([3, 0]) 

4540 

4541 """ 

4542 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

4543 

4544 m = self._mask 

4545 # special case for matrices (we assume no other subclasses modify 

4546 # their dimensions) 

4547 if isinstance(self.data, np.matrix): 

4548 if m is nomask: 

4549 m = np.zeros(self.shape, dtype=np.bool_) 

4550 m = m.view(type(self.data)) 

4551 

4552 if m is nomask: 

4553 # compare to _count_reduce_items in _methods.py 

4554 

4555 if self.shape == (): 

4556 if axis not in (None, 0): 

4557 raise np.AxisError(axis=axis, ndim=self.ndim) 

4558 return 1 

4559 elif axis is None: 

4560 if kwargs.get('keepdims', False): 

4561 return np.array(self.size, dtype=np.intp, ndmin=self.ndim) 

4562 return self.size 

4563 

4564 axes = normalize_axis_tuple(axis, self.ndim) 

4565 items = 1 

4566 for ax in axes: 

4567 items *= self.shape[ax] 

4568 

4569 if kwargs.get('keepdims', False): 

4570 out_dims = list(self.shape) 

4571 for a in axes: 

4572 out_dims[a] = 1 

4573 else: 

4574 out_dims = [d for n, d in enumerate(self.shape) 

4575 if n not in axes] 

4576 # make sure to return a 0-d array if axis is supplied 

4577 return np.full(out_dims, items, dtype=np.intp) 

4578 

4579 # take care of the masked singleton 

4580 if self is masked: 

4581 return 0 

4582 

4583 return (~m).sum(axis=axis, dtype=np.intp, **kwargs) 

4584 

4585 def ravel(self, order='C'): 

4586 """ 

4587 Returns a 1D version of self, as a view. 

4588 

4589 Parameters 

4590 ---------- 

4591 order : {'C', 'F', 'A', 'K'}, optional 

4592 The elements of `a` are read using this index order. 'C' means to 

4593 index the elements in C-like order, with the last axis index 

4594 changing fastest, back to the first axis index changing slowest. 

4595 'F' means to index the elements in Fortran-like index order, with 

4596 the first index changing fastest, and the last index changing 

4597 slowest. Note that the 'C' and 'F' options take no account of the 

4598 memory layout of the underlying array, and only refer to the order 

4599 of axis indexing. 'A' means to read the elements in Fortran-like 

4600 index order if `m` is Fortran *contiguous* in memory, C-like order 

4601 otherwise. 'K' means to read the elements in the order they occur 

4602 in memory, except for reversing the data when strides are negative. 

4603 By default, 'C' index order is used. 

4604 

4605 Returns 

4606 ------- 

4607 MaskedArray 

4608 Output view is of shape ``(self.size,)`` (or 

4609 ``(np.ma.product(self.shape),)``). 

4610 

4611 Examples 

4612 -------- 

4613 >>> x = np.ma.array([[1,2,3],[4,5,6],[7,8,9]], mask=[0] + [1,0]*4) 

4614 >>> x 

4615 masked_array( 

4616 data=[[1, --, 3], 

4617 [--, 5, --], 

4618 [7, --, 9]], 

4619 mask=[[False, True, False], 

4620 [ True, False, True], 

4621 [False, True, False]], 

4622 fill_value=999999) 

4623 >>> x.ravel() 

4624 masked_array(data=[1, --, 3, --, 5, --, 7, --, 9], 

4625 mask=[False, True, False, True, False, True, False, True, 

4626 False], 

4627 fill_value=999999) 

4628 

4629 """ 

4630 r = ndarray.ravel(self._data, order=order).view(type(self)) 

4631 r._update_from(self) 

4632 if self._mask is not nomask: 

4633 r._mask = ndarray.ravel(self._mask, order=order).reshape(r.shape) 

4634 else: 

4635 r._mask = nomask 

4636 return r 

4637 

4638 

4639 def reshape(self, *s, **kwargs): 

4640 """ 

4641 Give a new shape to the array without changing its data. 

4642 

4643 Returns a masked array containing the same data, but with a new shape. 

4644 The result is a view on the original array; if this is not possible, a 

4645 ValueError is raised. 

4646 

4647 Parameters 

4648 ---------- 

4649 shape : int or tuple of ints 

4650 The new shape should be compatible with the original shape. If an 

4651 integer is supplied, then the result will be a 1-D array of that 

4652 length. 

4653 order : {'C', 'F'}, optional 

4654 Determines whether the array data should be viewed as in C 

4655 (row-major) or FORTRAN (column-major) order. 

4656 

4657 Returns 

4658 ------- 

4659 reshaped_array : array 

4660 A new view on the array. 

4661 

4662 See Also 

4663 -------- 

4664 reshape : Equivalent function in the masked array module. 

4665 numpy.ndarray.reshape : Equivalent method on ndarray object. 

4666 numpy.reshape : Equivalent function in the NumPy module. 

4667 

4668 Notes 

4669 ----- 

4670 The reshaping operation cannot guarantee that a copy will not be made, 

4671 to modify the shape in place, use ``a.shape = s`` 

4672 

4673 Examples 

4674 -------- 

4675 >>> x = np.ma.array([[1,2],[3,4]], mask=[1,0,0,1]) 

4676 >>> x 

4677 masked_array( 

4678 data=[[--, 2], 

4679 [3, --]], 

4680 mask=[[ True, False], 

4681 [False, True]], 

4682 fill_value=999999) 

4683 >>> x = x.reshape((4,1)) 

4684 >>> x 

4685 masked_array( 

4686 data=[[--], 

4687 [2], 

4688 [3], 

4689 [--]], 

4690 mask=[[ True], 

4691 [False], 

4692 [False], 

4693 [ True]], 

4694 fill_value=999999) 

4695 

4696 """ 

4697 kwargs.update(order=kwargs.get('order', 'C')) 

4698 result = self._data.reshape(*s, **kwargs).view(type(self)) 

4699 result._update_from(self) 

4700 mask = self._mask 

4701 if mask is not nomask: 

4702 result._mask = mask.reshape(*s, **kwargs) 

4703 return result 

4704 

4705 def resize(self, newshape, refcheck=True, order=False): 

4706 """ 

4707 .. warning:: 

4708 

4709 This method does nothing, except raise a ValueError exception. A 

4710 masked array does not own its data and therefore cannot safely be 

4711 resized in place. Use the `numpy.ma.resize` function instead. 

4712 

4713 This method is difficult to implement safely and may be deprecated in 

4714 future releases of NumPy. 

4715 

4716 """ 

4717 # Note : the 'order' keyword looks broken, let's just drop it 

4718 errmsg = "A masked array does not own its data "\ 

4719 "and therefore cannot be resized.\n" \ 

4720 "Use the numpy.ma.resize function instead." 

4721 raise ValueError(errmsg) 

4722 

4723 def put(self, indices, values, mode='raise'): 

4724 """ 

4725 Set storage-indexed locations to corresponding values. 

4726 

4727 Sets self._data.flat[n] = values[n] for each n in indices. 

4728 If `values` is shorter than `indices` then it will repeat. 

4729 If `values` has some masked values, the initial mask is updated 

4730 in consequence, else the corresponding values are unmasked. 

4731 

4732 Parameters 

4733 ---------- 

4734 indices : 1-D array_like 

4735 Target indices, interpreted as integers. 

4736 values : array_like 

4737 Values to place in self._data copy at target indices. 

4738 mode : {'raise', 'wrap', 'clip'}, optional 

4739 Specifies how out-of-bounds indices will behave. 

4740 'raise' : raise an error. 

4741 'wrap' : wrap around. 

4742 'clip' : clip to the range. 

4743 

4744 Notes 

4745 ----- 

4746 `values` can be a scalar or length 1 array. 

4747 

4748 Examples 

4749 -------- 

4750 >>> x = np.ma.array([[1,2,3],[4,5,6],[7,8,9]], mask=[0] + [1,0]*4) 

4751 >>> x 

4752 masked_array( 

4753 data=[[1, --, 3], 

4754 [--, 5, --], 

4755 [7, --, 9]], 

4756 mask=[[False, True, False], 

4757 [ True, False, True], 

4758 [False, True, False]], 

4759 fill_value=999999) 

4760 >>> x.put([0,4,8],[10,20,30]) 

4761 >>> x 

4762 masked_array( 

4763 data=[[10, --, 3], 

4764 [--, 20, --], 

4765 [7, --, 30]], 

4766 mask=[[False, True, False], 

4767 [ True, False, True], 

4768 [False, True, False]], 

4769 fill_value=999999) 

4770 

4771 >>> x.put(4,999) 

4772 >>> x 

4773 masked_array( 

4774 data=[[10, --, 3], 

4775 [--, 999, --], 

4776 [7, --, 30]], 

4777 mask=[[False, True, False], 

4778 [ True, False, True], 

4779 [False, True, False]], 

4780 fill_value=999999) 

4781 

4782 """ 

4783 # Hard mask: Get rid of the values/indices that fall on masked data 

4784 if self._hardmask and self._mask is not nomask: 

4785 mask = self._mask[indices] 

4786 indices = narray(indices, copy=False) 

4787 values = narray(values, copy=False, subok=True) 

4788 values.resize(indices.shape) 

4789 indices = indices[~mask] 

4790 values = values[~mask] 

4791 

4792 self._data.put(indices, values, mode=mode) 

4793 

4794 # short circuit if neither self nor values are masked 

4795 if self._mask is nomask and getmask(values) is nomask: 

4796 return 

4797 

4798 m = getmaskarray(self) 

4799 

4800 if getmask(values) is nomask: 

4801 m.put(indices, False, mode=mode) 

4802 else: 

4803 m.put(indices, values._mask, mode=mode) 

4804 m = make_mask(m, copy=False, shrink=True) 

4805 self._mask = m 

4806 return 

4807 

4808 def ids(self): 

4809 """ 

4810 Return the addresses of the data and mask areas. 

4811 

4812 Parameters 

4813 ---------- 

4814 None 

4815 

4816 Examples 

4817 -------- 

4818 >>> x = np.ma.array([1, 2, 3], mask=[0, 1, 1]) 

4819 >>> x.ids() 

4820 (166670640, 166659832) # may vary 

4821 

4822 If the array has no mask, the address of `nomask` is returned. This address 

4823 is typically not close to the data in memory: 

4824 

4825 >>> x = np.ma.array([1, 2, 3]) 

4826 >>> x.ids() 

4827 (166691080, 3083169284) # may vary 

4828 

4829 """ 

4830 if self._mask is nomask: 

4831 return (self.ctypes.data, id(nomask)) 

4832 return (self.ctypes.data, self._mask.ctypes.data) 

4833 

4834 def iscontiguous(self): 

4835 """ 

4836 Return a boolean indicating whether the data is contiguous. 

4837 

4838 Parameters 

4839 ---------- 

4840 None 

4841 

4842 Examples 

4843 -------- 

4844 >>> x = np.ma.array([1, 2, 3]) 

4845 >>> x.iscontiguous() 

4846 True 

4847 

4848 `iscontiguous` returns one of the flags of the masked array: 

4849 

4850 >>> x.flags 

4851 C_CONTIGUOUS : True 

4852 F_CONTIGUOUS : True 

4853 OWNDATA : False 

4854 WRITEABLE : True 

4855 ALIGNED : True 

4856 WRITEBACKIFCOPY : False 

4857 

4858 """ 

4859 return self.flags['CONTIGUOUS'] 

4860 

4861 def all(self, axis=None, out=None, keepdims=np._NoValue): 

4862 """ 

4863 Returns True if all elements evaluate to True. 

4864 

4865 The output array is masked where all the values along the given axis 

4866 are masked: if the output would have been a scalar and that all the 

4867 values are masked, then the output is `masked`. 

4868 

4869 Refer to `numpy.all` for full documentation. 

4870 

4871 See Also 

4872 -------- 

4873 numpy.ndarray.all : corresponding function for ndarrays 

4874 numpy.all : equivalent function 

4875 

4876 Examples 

4877 -------- 

4878 >>> np.ma.array([1,2,3]).all() 

4879 True 

4880 >>> a = np.ma.array([1,2,3], mask=True) 

4881 >>> (a.all() is np.ma.masked) 

4882 True 

4883 

4884 """ 

4885 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

4886 

4887 mask = _check_mask_axis(self._mask, axis, **kwargs) 

4888 if out is None: 

4889 d = self.filled(True).all(axis=axis, **kwargs).view(type(self)) 

4890 if d.ndim: 

4891 d.__setmask__(mask) 

4892 elif mask: 

4893 return masked 

4894 return d 

4895 self.filled(True).all(axis=axis, out=out, **kwargs) 

4896 if isinstance(out, MaskedArray): 

4897 if out.ndim or mask: 

4898 out.__setmask__(mask) 

4899 return out 

4900 

4901 def any(self, axis=None, out=None, keepdims=np._NoValue): 

4902 """ 

4903 Returns True if any of the elements of `a` evaluate to True. 

4904 

4905 Masked values are considered as False during computation. 

4906 

4907 Refer to `numpy.any` for full documentation. 

4908 

4909 See Also 

4910 -------- 

4911 numpy.ndarray.any : corresponding function for ndarrays 

4912 numpy.any : equivalent function 

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(False).any(axis=axis, **kwargs).view(type(self)) 

4920 if d.ndim: 

4921 d.__setmask__(mask) 

4922 elif mask: 

4923 d = masked 

4924 return d 

4925 self.filled(False).any(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 nonzero(self): 

4932 """ 

4933 Return the indices of unmasked elements that are not zero. 

4934 

4935 Returns a tuple of arrays, one for each dimension, containing the 

4936 indices of the non-zero elements in that dimension. The corresponding 

4937 non-zero values can be obtained with:: 

4938 

4939 a[a.nonzero()] 

4940 

4941 To group the indices by element, rather than dimension, use 

4942 instead:: 

4943 

4944 np.transpose(a.nonzero()) 

4945 

4946 The result of this is always a 2d array, with a row for each non-zero 

4947 element. 

4948 

4949 Parameters 

4950 ---------- 

4951 None 

4952 

4953 Returns 

4954 ------- 

4955 tuple_of_arrays : tuple 

4956 Indices of elements that are non-zero. 

4957 

4958 See Also 

4959 -------- 

4960 numpy.nonzero : 

4961 Function operating on ndarrays. 

4962 flatnonzero : 

4963 Return indices that are non-zero in the flattened version of the input 

4964 array. 

4965 numpy.ndarray.nonzero : 

4966 Equivalent ndarray method. 

4967 count_nonzero : 

4968 Counts the number of non-zero elements in the input array. 

4969 

4970 Examples 

4971 -------- 

4972 >>> import numpy.ma as ma 

4973 >>> x = ma.array(np.eye(3)) 

4974 >>> x 

4975 masked_array( 

4976 data=[[1., 0., 0.], 

4977 [0., 1., 0.], 

4978 [0., 0., 1.]], 

4979 mask=False, 

4980 fill_value=1e+20) 

4981 >>> x.nonzero() 

4982 (array([0, 1, 2]), array([0, 1, 2])) 

4983 

4984 Masked elements are ignored. 

4985 

4986 >>> x[1, 1] = ma.masked 

4987 >>> x 

4988 masked_array( 

4989 data=[[1.0, 0.0, 0.0], 

4990 [0.0, --, 0.0], 

4991 [0.0, 0.0, 1.0]], 

4992 mask=[[False, False, False], 

4993 [False, True, False], 

4994 [False, False, False]], 

4995 fill_value=1e+20) 

4996 >>> x.nonzero() 

4997 (array([0, 2]), array([0, 2])) 

4998 

4999 Indices can also be grouped by element. 

5000 

5001 >>> np.transpose(x.nonzero()) 

5002 array([[0, 0], 

5003 [2, 2]]) 

5004 

5005 A common use for ``nonzero`` is to find the indices of an array, where 

5006 a condition is True. Given an array `a`, the condition `a` > 3 is a 

5007 boolean array and since False is interpreted as 0, ma.nonzero(a > 3) 

5008 yields the indices of the `a` where the condition is true. 

5009 

5010 >>> a = ma.array([[1,2,3],[4,5,6],[7,8,9]]) 

5011 >>> a > 3 

5012 masked_array( 

5013 data=[[False, False, False], 

5014 [ True, True, True], 

5015 [ True, True, True]], 

5016 mask=False, 

5017 fill_value=True) 

5018 >>> ma.nonzero(a > 3) 

5019 (array([1, 1, 1, 2, 2, 2]), array([0, 1, 2, 0, 1, 2])) 

5020 

5021 The ``nonzero`` method of the condition array can also be called. 

5022 

5023 >>> (a > 3).nonzero() 

5024 (array([1, 1, 1, 2, 2, 2]), array([0, 1, 2, 0, 1, 2])) 

5025 

5026 """ 

5027 return narray(self.filled(0), copy=False).nonzero() 

5028 

5029 def trace(self, offset=0, axis1=0, axis2=1, dtype=None, out=None): 

5030 """ 

5031 (this docstring should be overwritten) 

5032 """ 

5033 #!!!: implement out + test! 

5034 m = self._mask 

5035 if m is nomask: 

5036 result = super().trace(offset=offset, axis1=axis1, axis2=axis2, 

5037 out=out) 

5038 return result.astype(dtype) 

5039 else: 

5040 D = self.diagonal(offset=offset, axis1=axis1, axis2=axis2) 

5041 return D.astype(dtype).filled(0).sum(axis=-1, out=out) 

5042 trace.__doc__ = ndarray.trace.__doc__ 

5043 

5044 def dot(self, b, out=None, strict=False): 

5045 """ 

5046 a.dot(b, out=None) 

5047 

5048 Masked dot product of two arrays. Note that `out` and `strict` are 

5049 located in different positions than in `ma.dot`. In order to 

5050 maintain compatibility with the functional version, it is 

5051 recommended that the optional arguments be treated as keyword only. 

5052 At some point that may be mandatory. 

5053 

5054 .. versionadded:: 1.10.0 

5055 

5056 Parameters 

5057 ---------- 

5058 b : masked_array_like 

5059 Inputs array. 

5060 out : masked_array, optional 

5061 Output argument. This must have the exact kind that would be 

5062 returned if it was not used. In particular, it must have the 

5063 right type, must be C-contiguous, and its dtype must be the 

5064 dtype that would be returned for `ma.dot(a,b)`. This is a 

5065 performance feature. Therefore, if these conditions are not 

5066 met, an exception is raised, instead of attempting to be 

5067 flexible. 

5068 strict : bool, optional 

5069 Whether masked data are propagated (True) or set to 0 (False) 

5070 for the computation. Default is False. Propagating the mask 

5071 means that if a masked value appears in a row or column, the 

5072 whole row or column is considered masked. 

5073 

5074 .. versionadded:: 1.10.2 

5075 

5076 See Also 

5077 -------- 

5078 numpy.ma.dot : equivalent function 

5079 

5080 """ 

5081 return dot(self, b, out=out, strict=strict) 

5082 

5083 def sum(self, axis=None, dtype=None, out=None, keepdims=np._NoValue): 

5084 """ 

5085 Return the sum of the array elements over the given axis. 

5086 

5087 Masked elements are set to 0 internally. 

5088 

5089 Refer to `numpy.sum` for full documentation. 

5090 

5091 See Also 

5092 -------- 

5093 numpy.ndarray.sum : corresponding function for ndarrays 

5094 numpy.sum : equivalent function 

5095 

5096 Examples 

5097 -------- 

5098 >>> x = np.ma.array([[1,2,3],[4,5,6],[7,8,9]], mask=[0] + [1,0]*4) 

5099 >>> x 

5100 masked_array( 

5101 data=[[1, --, 3], 

5102 [--, 5, --], 

5103 [7, --, 9]], 

5104 mask=[[False, True, False], 

5105 [ True, False, True], 

5106 [False, True, False]], 

5107 fill_value=999999) 

5108 >>> x.sum() 

5109 25 

5110 >>> x.sum(axis=1) 

5111 masked_array(data=[4, 5, 16], 

5112 mask=[False, False, False], 

5113 fill_value=999999) 

5114 >>> x.sum(axis=0) 

5115 masked_array(data=[8, 5, 12], 

5116 mask=[False, False, False], 

5117 fill_value=999999) 

5118 >>> print(type(x.sum(axis=0, dtype=np.int64)[0])) 

5119 <class 'numpy.int64'> 

5120 

5121 """ 

5122 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

5123 

5124 _mask = self._mask 

5125 newmask = _check_mask_axis(_mask, axis, **kwargs) 

5126 # No explicit output 

5127 if out is None: 

5128 result = self.filled(0).sum(axis, dtype=dtype, **kwargs) 

5129 rndim = getattr(result, 'ndim', 0) 

5130 if rndim: 

5131 result = result.view(type(self)) 

5132 result.__setmask__(newmask) 

5133 elif newmask: 

5134 result = masked 

5135 return result 

5136 # Explicit output 

5137 result = self.filled(0).sum(axis, dtype=dtype, out=out, **kwargs) 

5138 if isinstance(out, MaskedArray): 

5139 outmask = getmask(out) 

5140 if outmask is nomask: 

5141 outmask = out._mask = make_mask_none(out.shape) 

5142 outmask.flat = newmask 

5143 return out 

5144 

5145 def cumsum(self, axis=None, dtype=None, out=None): 

5146 """ 

5147 Return the cumulative sum of the array elements over the given axis. 

5148 

5149 Masked values are set to 0 internally during the computation. 

5150 However, their position is saved, and the result will be masked at 

5151 the same locations. 

5152 

5153 Refer to `numpy.cumsum` for full documentation. 

5154 

5155 Notes 

5156 ----- 

5157 The mask is lost if `out` is not a valid :class:`ma.MaskedArray` ! 

5158 

5159 Arithmetic is modular when using integer types, and no error is 

5160 raised on overflow. 

5161 

5162 See Also 

5163 -------- 

5164 numpy.ndarray.cumsum : corresponding function for ndarrays 

5165 numpy.cumsum : equivalent function 

5166 

5167 Examples 

5168 -------- 

5169 >>> marr = np.ma.array(np.arange(10), mask=[0,0,0,1,1,1,0,0,0,0]) 

5170 >>> marr.cumsum() 

5171 masked_array(data=[0, 1, 3, --, --, --, 9, 16, 24, 33], 

5172 mask=[False, False, False, True, True, True, False, False, 

5173 False, False], 

5174 fill_value=999999) 

5175 

5176 """ 

5177 result = self.filled(0).cumsum(axis=axis, dtype=dtype, out=out) 

5178 if out is not None: 

5179 if isinstance(out, MaskedArray): 

5180 out.__setmask__(self.mask) 

5181 return out 

5182 result = result.view(type(self)) 

5183 result.__setmask__(self._mask) 

5184 return result 

5185 

5186 def prod(self, axis=None, dtype=None, out=None, keepdims=np._NoValue): 

5187 """ 

5188 Return the product of the array elements over the given axis. 

5189 

5190 Masked elements are set to 1 internally for computation. 

5191 

5192 Refer to `numpy.prod` for full documentation. 

5193 

5194 Notes 

5195 ----- 

5196 Arithmetic is modular when using integer types, and no error is raised 

5197 on overflow. 

5198 

5199 See Also 

5200 -------- 

5201 numpy.ndarray.prod : corresponding function for ndarrays 

5202 numpy.prod : equivalent function 

5203 """ 

5204 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

5205 

5206 _mask = self._mask 

5207 newmask = _check_mask_axis(_mask, axis, **kwargs) 

5208 # No explicit output 

5209 if out is None: 

5210 result = self.filled(1).prod(axis, dtype=dtype, **kwargs) 

5211 rndim = getattr(result, 'ndim', 0) 

5212 if rndim: 

5213 result = result.view(type(self)) 

5214 result.__setmask__(newmask) 

5215 elif newmask: 

5216 result = masked 

5217 return result 

5218 # Explicit output 

5219 result = self.filled(1).prod(axis, dtype=dtype, out=out, **kwargs) 

5220 if isinstance(out, MaskedArray): 

5221 outmask = getmask(out) 

5222 if outmask is nomask: 

5223 outmask = out._mask = make_mask_none(out.shape) 

5224 outmask.flat = newmask 

5225 return out 

5226 product = prod 

5227 

5228 def cumprod(self, axis=None, dtype=None, out=None): 

5229 """ 

5230 Return the cumulative product of the array elements over the given axis. 

5231 

5232 Masked values are set to 1 internally during the computation. 

5233 However, their position is saved, and the result will be masked at 

5234 the same locations. 

5235 

5236 Refer to `numpy.cumprod` for full documentation. 

5237 

5238 Notes 

5239 ----- 

5240 The mask is lost if `out` is not a valid MaskedArray ! 

5241 

5242 Arithmetic is modular when using integer types, and no error is 

5243 raised on overflow. 

5244 

5245 See Also 

5246 -------- 

5247 numpy.ndarray.cumprod : corresponding function for ndarrays 

5248 numpy.cumprod : equivalent function 

5249 """ 

5250 result = self.filled(1).cumprod(axis=axis, dtype=dtype, out=out) 

5251 if out is not None: 

5252 if isinstance(out, MaskedArray): 

5253 out.__setmask__(self._mask) 

5254 return out 

5255 result = result.view(type(self)) 

5256 result.__setmask__(self._mask) 

5257 return result 

5258 

5259 def mean(self, axis=None, dtype=None, out=None, keepdims=np._NoValue): 

5260 """ 

5261 Returns the average of the array elements along given axis. 

5262 

5263 Masked entries are ignored, and result elements which are not 

5264 finite will be masked. 

5265 

5266 Refer to `numpy.mean` for full documentation. 

5267 

5268 See Also 

5269 -------- 

5270 numpy.ndarray.mean : corresponding function for ndarrays 

5271 numpy.mean : Equivalent function 

5272 numpy.ma.average : Weighted average. 

5273 

5274 Examples 

5275 -------- 

5276 >>> a = np.ma.array([1,2,3], mask=[False, False, True]) 

5277 >>> a 

5278 masked_array(data=[1, 2, --], 

5279 mask=[False, False, True], 

5280 fill_value=999999) 

5281 >>> a.mean() 

5282 1.5 

5283 

5284 """ 

5285 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

5286 

5287 if self._mask is nomask: 

5288 result = super().mean(axis=axis, dtype=dtype, **kwargs)[()] 

5289 else: 

5290 dsum = self.sum(axis=axis, dtype=dtype, **kwargs) 

5291 cnt = self.count(axis=axis, **kwargs) 

5292 if cnt.shape == () and (cnt == 0): 

5293 result = masked 

5294 else: 

5295 result = dsum * 1. / cnt 

5296 if out is not None: 

5297 out.flat = result 

5298 if isinstance(out, MaskedArray): 

5299 outmask = getmask(out) 

5300 if outmask is nomask: 

5301 outmask = out._mask = make_mask_none(out.shape) 

5302 outmask.flat = getmask(result) 

5303 return out 

5304 return result 

5305 

5306 def anom(self, axis=None, dtype=None): 

5307 """ 

5308 Compute the anomalies (deviations from the arithmetic mean) 

5309 along the given axis. 

5310 

5311 Returns an array of anomalies, with the same shape as the input and 

5312 where the arithmetic mean is computed along the given axis. 

5313 

5314 Parameters 

5315 ---------- 

5316 axis : int, optional 

5317 Axis over which the anomalies are taken. 

5318 The default is to use the mean of the flattened array as reference. 

5319 dtype : dtype, optional 

5320 Type to use in computing the variance. For arrays of integer type 

5321 the default is float32; for arrays of float types it is the same as 

5322 the array type. 

5323 

5324 See Also 

5325 -------- 

5326 mean : Compute the mean of the array. 

5327 

5328 Examples 

5329 -------- 

5330 >>> a = np.ma.array([1,2,3]) 

5331 >>> a.anom() 

5332 masked_array(data=[-1., 0., 1.], 

5333 mask=False, 

5334 fill_value=1e+20) 

5335 

5336 """ 

5337 m = self.mean(axis, dtype) 

5338 if not axis: 

5339 return self - m 

5340 else: 

5341 return self - expand_dims(m, axis) 

5342 

5343 def var(self, axis=None, dtype=None, out=None, ddof=0, 

5344 keepdims=np._NoValue): 

5345 """ 

5346 Returns the variance of the array elements along given axis. 

5347 

5348 Masked entries are ignored, and result elements which are not 

5349 finite will be masked. 

5350 

5351 Refer to `numpy.var` for full documentation. 

5352 

5353 See Also 

5354 -------- 

5355 numpy.ndarray.var : corresponding function for ndarrays 

5356 numpy.var : Equivalent function 

5357 """ 

5358 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

5359 

5360 # Easy case: nomask, business as usual 

5361 if self._mask is nomask: 

5362 ret = super().var(axis=axis, dtype=dtype, out=out, ddof=ddof, 

5363 **kwargs)[()] 

5364 if out is not None: 

5365 if isinstance(out, MaskedArray): 

5366 out.__setmask__(nomask) 

5367 return out 

5368 return ret 

5369 

5370 # Some data are masked, yay! 

5371 cnt = self.count(axis=axis, **kwargs) - ddof 

5372 danom = self - self.mean(axis, dtype, keepdims=True) 

5373 if iscomplexobj(self): 

5374 danom = umath.absolute(danom) ** 2 

5375 else: 

5376 danom *= danom 

5377 dvar = divide(danom.sum(axis, **kwargs), cnt).view(type(self)) 

5378 # Apply the mask if it's not a scalar 

5379 if dvar.ndim: 

5380 dvar._mask = mask_or(self._mask.all(axis, **kwargs), (cnt <= 0)) 

5381 dvar._update_from(self) 

5382 elif getmask(dvar): 

5383 # Make sure that masked is returned when the scalar is masked. 

5384 dvar = masked 

5385 if out is not None: 

5386 if isinstance(out, MaskedArray): 

5387 out.flat = 0 

5388 out.__setmask__(True) 

5389 elif out.dtype.kind in 'biu': 

5390 errmsg = "Masked data information would be lost in one or "\ 

5391 "more location." 

5392 raise MaskError(errmsg) 

5393 else: 

5394 out.flat = np.nan 

5395 return out 

5396 # In case with have an explicit output 

5397 if out is not None: 

5398 # Set the data 

5399 out.flat = dvar 

5400 # Set the mask if needed 

5401 if isinstance(out, MaskedArray): 

5402 out.__setmask__(dvar.mask) 

5403 return out 

5404 return dvar 

5405 var.__doc__ = np.var.__doc__ 

5406 

5407 def std(self, axis=None, dtype=None, out=None, ddof=0, 

5408 keepdims=np._NoValue): 

5409 """ 

5410 Returns the standard deviation of the array elements along given axis. 

5411 

5412 Masked entries are ignored. 

5413 

5414 Refer to `numpy.std` for full documentation. 

5415 

5416 See Also 

5417 -------- 

5418 numpy.ndarray.std : corresponding function for ndarrays 

5419 numpy.std : Equivalent function 

5420 """ 

5421 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

5422 

5423 dvar = self.var(axis, dtype, out, ddof, **kwargs) 

5424 if dvar is not masked: 

5425 if out is not None: 

5426 np.power(out, 0.5, out=out, casting='unsafe') 

5427 return out 

5428 dvar = sqrt(dvar) 

5429 return dvar 

5430 

5431 def round(self, decimals=0, out=None): 

5432 """ 

5433 Return each element rounded to the given number of decimals. 

5434 

5435 Refer to `numpy.around` for full documentation. 

5436 

5437 See Also 

5438 -------- 

5439 numpy.ndarray.round : corresponding function for ndarrays 

5440 numpy.around : equivalent function 

5441 """ 

5442 result = self._data.round(decimals=decimals, out=out).view(type(self)) 

5443 if result.ndim > 0: 

5444 result._mask = self._mask 

5445 result._update_from(self) 

5446 elif self._mask: 

5447 # Return masked when the scalar is masked 

5448 result = masked 

5449 # No explicit output: we're done 

5450 if out is None: 

5451 return result 

5452 if isinstance(out, MaskedArray): 

5453 out.__setmask__(self._mask) 

5454 return out 

5455 

5456 def argsort(self, axis=np._NoValue, kind=None, order=None, 

5457 endwith=True, fill_value=None): 

5458 """ 

5459 Return an ndarray of indices that sort the array along the 

5460 specified axis. Masked values are filled beforehand to 

5461 `fill_value`. 

5462 

5463 Parameters 

5464 ---------- 

5465 axis : int, optional 

5466 Axis along which to sort. If None, the default, the flattened array 

5467 is used. 

5468 

5469 .. versionchanged:: 1.13.0 

5470 Previously, the default was documented to be -1, but that was 

5471 in error. At some future date, the default will change to -1, as 

5472 originally intended. 

5473 Until then, the axis should be given explicitly when 

5474 ``arr.ndim > 1``, to avoid a FutureWarning. 

5475 kind : {'quicksort', 'mergesort', 'heapsort', 'stable'}, optional 

5476 The sorting algorithm used. 

5477 order : list, optional 

5478 When `a` is an array with fields defined, this argument specifies 

5479 which fields to compare first, second, etc. Not all fields need be 

5480 specified. 

5481 endwith : {True, False}, optional 

5482 Whether missing values (if any) should be treated as the largest values 

5483 (True) or the smallest values (False) 

5484 When the array contains unmasked values at the same extremes of the 

5485 datatype, the ordering of these values and the masked values is 

5486 undefined. 

5487 fill_value : scalar or None, optional 

5488 Value used internally for the masked values. 

5489 If ``fill_value`` is not None, it supersedes ``endwith``. 

5490 

5491 Returns 

5492 ------- 

5493 index_array : ndarray, int 

5494 Array of indices that sort `a` along the specified axis. 

5495 In other words, ``a[index_array]`` yields a sorted `a`. 

5496 

5497 See Also 

5498 -------- 

5499 ma.MaskedArray.sort : Describes sorting algorithms used. 

5500 lexsort : Indirect stable sort with multiple keys. 

5501 numpy.ndarray.sort : Inplace sort. 

5502 

5503 Notes 

5504 ----- 

5505 See `sort` for notes on the different sorting algorithms. 

5506 

5507 Examples 

5508 -------- 

5509 >>> a = np.ma.array([3,2,1], mask=[False, False, True]) 

5510 >>> a 

5511 masked_array(data=[3, 2, --], 

5512 mask=[False, False, True], 

5513 fill_value=999999) 

5514 >>> a.argsort() 

5515 array([1, 0, 2]) 

5516 

5517 """ 

5518 

5519 # 2017-04-11, Numpy 1.13.0, gh-8701: warn on axis default 

5520 if axis is np._NoValue: 

5521 axis = _deprecate_argsort_axis(self) 

5522 

5523 if fill_value is None: 

5524 if endwith: 

5525 # nan > inf 

5526 if np.issubdtype(self.dtype, np.floating): 

5527 fill_value = np.nan 

5528 else: 

5529 fill_value = minimum_fill_value(self) 

5530 else: 

5531 fill_value = maximum_fill_value(self) 

5532 

5533 filled = self.filled(fill_value) 

5534 return filled.argsort(axis=axis, kind=kind, order=order) 

5535 

5536 def argmin(self, axis=None, fill_value=None, out=None, *, 

5537 keepdims=np._NoValue): 

5538 """ 

5539 Return array of indices to the minimum values along the given axis. 

5540 

5541 Parameters 

5542 ---------- 

5543 axis : {None, integer} 

5544 If None, the index is into the flattened array, otherwise along 

5545 the specified axis 

5546 fill_value : scalar or None, optional 

5547 Value used to fill in the masked values. If None, the output of 

5548 minimum_fill_value(self._data) is used instead. 

5549 out : {None, array}, optional 

5550 Array into which the result can be placed. Its type is preserved 

5551 and it must be of the right shape to hold the output. 

5552 

5553 Returns 

5554 ------- 

5555 ndarray or scalar 

5556 If multi-dimension input, returns a new ndarray of indices to the 

5557 minimum values along the given axis. Otherwise, returns a scalar 

5558 of index to the minimum values along the given axis. 

5559 

5560 Examples 

5561 -------- 

5562 >>> x = np.ma.array(np.arange(4), mask=[1,1,0,0]) 

5563 >>> x.shape = (2,2) 

5564 >>> x 

5565 masked_array( 

5566 data=[[--, --], 

5567 [2, 3]], 

5568 mask=[[ True, True], 

5569 [False, False]], 

5570 fill_value=999999) 

5571 >>> x.argmin(axis=0, fill_value=-1) 

5572 array([0, 0]) 

5573 >>> x.argmin(axis=0, fill_value=9) 

5574 array([1, 1]) 

5575 

5576 """ 

5577 if fill_value is None: 

5578 fill_value = minimum_fill_value(self) 

5579 d = self.filled(fill_value).view(ndarray) 

5580 keepdims = False if keepdims is np._NoValue else bool(keepdims) 

5581 return d.argmin(axis, out=out, keepdims=keepdims) 

5582 

5583 def argmax(self, axis=None, fill_value=None, out=None, *, 

5584 keepdims=np._NoValue): 

5585 """ 

5586 Returns array of indices of the maximum values along the given axis. 

5587 Masked values are treated as if they had the value fill_value. 

5588 

5589 Parameters 

5590 ---------- 

5591 axis : {None, integer} 

5592 If None, the index is into the flattened array, otherwise along 

5593 the specified axis 

5594 fill_value : scalar or None, optional 

5595 Value used to fill in the masked values. If None, the output of 

5596 maximum_fill_value(self._data) is used instead. 

5597 out : {None, array}, optional 

5598 Array into which the result can be placed. Its type is preserved 

5599 and it must be of the right shape to hold the output. 

5600 

5601 Returns 

5602 ------- 

5603 index_array : {integer_array} 

5604 

5605 Examples 

5606 -------- 

5607 >>> a = np.arange(6).reshape(2,3) 

5608 >>> a.argmax() 

5609 5 

5610 >>> a.argmax(0) 

5611 array([1, 1, 1]) 

5612 >>> a.argmax(1) 

5613 array([2, 2]) 

5614 

5615 """ 

5616 if fill_value is None: 

5617 fill_value = maximum_fill_value(self._data) 

5618 d = self.filled(fill_value).view(ndarray) 

5619 keepdims = False if keepdims is np._NoValue else bool(keepdims) 

5620 return d.argmax(axis, out=out, keepdims=keepdims) 

5621 

5622 def sort(self, axis=-1, kind=None, order=None, 

5623 endwith=True, fill_value=None): 

5624 """ 

5625 Sort the array, in-place 

5626 

5627 Parameters 

5628 ---------- 

5629 a : array_like 

5630 Array to be sorted. 

5631 axis : int, optional 

5632 Axis along which to sort. If None, the array is flattened before 

5633 sorting. The default is -1, which sorts along the last axis. 

5634 kind : {'quicksort', 'mergesort', 'heapsort', 'stable'}, optional 

5635 The sorting algorithm used. 

5636 order : list, optional 

5637 When `a` is a structured array, this argument specifies which fields 

5638 to compare first, second, and so on. This list does not need to 

5639 include all of the fields. 

5640 endwith : {True, False}, optional 

5641 Whether missing values (if any) should be treated as the largest values 

5642 (True) or the smallest values (False) 

5643 When the array contains unmasked values sorting at the same extremes of the 

5644 datatype, the ordering of these values and the masked values is 

5645 undefined. 

5646 fill_value : scalar or None, optional 

5647 Value used internally for the masked values. 

5648 If ``fill_value`` is not None, it supersedes ``endwith``. 

5649 

5650 Returns 

5651 ------- 

5652 sorted_array : ndarray 

5653 Array of the same type and shape as `a`. 

5654 

5655 See Also 

5656 -------- 

5657 numpy.ndarray.sort : Method to sort an array in-place. 

5658 argsort : Indirect sort. 

5659 lexsort : Indirect stable sort on multiple keys. 

5660 searchsorted : Find elements in a sorted array. 

5661 

5662 Notes 

5663 ----- 

5664 See ``sort`` for notes on the different sorting algorithms. 

5665 

5666 Examples 

5667 -------- 

5668 >>> a = np.ma.array([1, 2, 5, 4, 3],mask=[0, 1, 0, 1, 0]) 

5669 >>> # Default 

5670 >>> a.sort() 

5671 >>> a 

5672 masked_array(data=[1, 3, 5, --, --], 

5673 mask=[False, False, False, True, True], 

5674 fill_value=999999) 

5675 

5676 >>> a = np.ma.array([1, 2, 5, 4, 3],mask=[0, 1, 0, 1, 0]) 

5677 >>> # Put missing values in the front 

5678 >>> a.sort(endwith=False) 

5679 >>> a 

5680 masked_array(data=[--, --, 1, 3, 5], 

5681 mask=[ True, True, False, False, False], 

5682 fill_value=999999) 

5683 

5684 >>> a = np.ma.array([1, 2, 5, 4, 3],mask=[0, 1, 0, 1, 0]) 

5685 >>> # fill_value takes over endwith 

5686 >>> a.sort(endwith=False, fill_value=3) 

5687 >>> a 

5688 masked_array(data=[1, --, --, 3, 5], 

5689 mask=[False, True, True, False, False], 

5690 fill_value=999999) 

5691 

5692 """ 

5693 if self._mask is nomask: 

5694 ndarray.sort(self, axis=axis, kind=kind, order=order) 

5695 return 

5696 

5697 if self is masked: 

5698 return 

5699 

5700 sidx = self.argsort(axis=axis, kind=kind, order=order, 

5701 fill_value=fill_value, endwith=endwith) 

5702 

5703 self[...] = np.take_along_axis(self, sidx, axis=axis) 

5704 

5705 def min(self, axis=None, out=None, fill_value=None, keepdims=np._NoValue): 

5706 """ 

5707 Return the minimum along a given axis. 

5708 

5709 Parameters 

5710 ---------- 

5711 axis : None or int or tuple of ints, optional 

5712 Axis along which to operate. By default, ``axis`` is None and the 

5713 flattened input is used. 

5714 .. versionadded:: 1.7.0 

5715 If this is a tuple of ints, the minimum is selected over multiple 

5716 axes, instead of a single axis or all the axes as before. 

5717 out : array_like, optional 

5718 Alternative output array in which to place the result. Must be of 

5719 the same shape and buffer length as the expected output. 

5720 fill_value : scalar or None, optional 

5721 Value used to fill in the masked values. 

5722 If None, use the output of `minimum_fill_value`. 

5723 keepdims : bool, optional 

5724 If this is set to True, the axes which are reduced are left 

5725 in the result as dimensions with size one. With this option, 

5726 the result will broadcast correctly against the array. 

5727 

5728 Returns 

5729 ------- 

5730 amin : array_like 

5731 New array holding the result. 

5732 If ``out`` was specified, ``out`` is returned. 

5733 

5734 See Also 

5735 -------- 

5736 ma.minimum_fill_value 

5737 Returns the minimum filling value for a given datatype. 

5738 

5739 """ 

5740 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

5741 

5742 _mask = self._mask 

5743 newmask = _check_mask_axis(_mask, axis, **kwargs) 

5744 if fill_value is None: 

5745 fill_value = minimum_fill_value(self) 

5746 # No explicit output 

5747 if out is None: 

5748 result = self.filled(fill_value).min( 

5749 axis=axis, out=out, **kwargs).view(type(self)) 

5750 if result.ndim: 

5751 # Set the mask 

5752 result.__setmask__(newmask) 

5753 # Get rid of Infs 

5754 if newmask.ndim: 

5755 np.copyto(result, result.fill_value, where=newmask) 

5756 elif newmask: 

5757 result = masked 

5758 return result 

5759 # Explicit output 

5760 result = self.filled(fill_value).min(axis=axis, out=out, **kwargs) 

5761 if isinstance(out, MaskedArray): 

5762 outmask = getmask(out) 

5763 if outmask is nomask: 

5764 outmask = out._mask = make_mask_none(out.shape) 

5765 outmask.flat = newmask 

5766 else: 

5767 if out.dtype.kind in 'biu': 

5768 errmsg = "Masked data information would be lost in one or more"\ 

5769 " location." 

5770 raise MaskError(errmsg) 

5771 np.copyto(out, np.nan, where=newmask) 

5772 return out 

5773 

5774 # unique to masked arrays 

5775 def mini(self, axis=None): 

5776 """ 

5777 Return the array minimum along the specified axis. 

5778 

5779 .. deprecated:: 1.13.0 

5780 This function is identical to both: 

5781 

5782 * ``self.min(keepdims=True, axis=axis).squeeze(axis=axis)`` 

5783 * ``np.ma.minimum.reduce(self, axis=axis)`` 

5784 

5785 Typically though, ``self.min(axis=axis)`` is sufficient. 

5786 

5787 Parameters 

5788 ---------- 

5789 axis : int, optional 

5790 The axis along which to find the minima. Default is None, in which case 

5791 the minimum value in the whole array is returned. 

5792 

5793 Returns 

5794 ------- 

5795 min : scalar or MaskedArray 

5796 If `axis` is None, the result is a scalar. Otherwise, if `axis` is 

5797 given and the array is at least 2-D, the result is a masked array with 

5798 dimension one smaller than the array on which `mini` is called. 

5799 

5800 Examples 

5801 -------- 

5802 >>> x = np.ma.array(np.arange(6), mask=[0 ,1, 0, 0, 0 ,1]).reshape(3, 2) 

5803 >>> x 

5804 masked_array( 

5805 data=[[0, --], 

5806 [2, 3], 

5807 [4, --]], 

5808 mask=[[False, True], 

5809 [False, False], 

5810 [False, True]], 

5811 fill_value=999999) 

5812 >>> x.mini() 

5813 masked_array(data=0, 

5814 mask=False, 

5815 fill_value=999999) 

5816 >>> x.mini(axis=0) 

5817 masked_array(data=[0, 3], 

5818 mask=[False, False], 

5819 fill_value=999999) 

5820 >>> x.mini(axis=1) 

5821 masked_array(data=[0, 2, 4], 

5822 mask=[False, False, False], 

5823 fill_value=999999) 

5824 

5825 There is a small difference between `mini` and `min`: 

5826 

5827 >>> x[:,1].mini(axis=0) 

5828 masked_array(data=3, 

5829 mask=False, 

5830 fill_value=999999) 

5831 >>> x[:,1].min(axis=0) 

5832 3 

5833 """ 

5834 

5835 # 2016-04-13, 1.13.0, gh-8764 

5836 warnings.warn( 

5837 "`mini` is deprecated; use the `min` method or " 

5838 "`np.ma.minimum.reduce instead.", 

5839 DeprecationWarning, stacklevel=2) 

5840 return minimum.reduce(self, axis) 

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 """ 

5877 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

5878 

5879 _mask = self._mask 

5880 newmask = _check_mask_axis(_mask, axis, **kwargs) 

5881 if fill_value is None: 

5882 fill_value = maximum_fill_value(self) 

5883 # No explicit output 

5884 if out is None: 

5885 result = self.filled(fill_value).max( 

5886 axis=axis, out=out, **kwargs).view(type(self)) 

5887 if result.ndim: 

5888 # Set the mask 

5889 result.__setmask__(newmask) 

5890 # Get rid of Infs 

5891 if newmask.ndim: 

5892 np.copyto(result, result.fill_value, where=newmask) 

5893 elif newmask: 

5894 result = masked 

5895 return result 

5896 # Explicit output 

5897 result = self.filled(fill_value).max(axis=axis, out=out, **kwargs) 

5898 if isinstance(out, MaskedArray): 

5899 outmask = getmask(out) 

5900 if outmask is nomask: 

5901 outmask = out._mask = make_mask_none(out.shape) 

5902 outmask.flat = newmask 

5903 else: 

5904 

5905 if out.dtype.kind in 'biu': 

5906 errmsg = "Masked data information would be lost in one or more"\ 

5907 " location." 

5908 raise MaskError(errmsg) 

5909 np.copyto(out, np.nan, where=newmask) 

5910 return out 

5911 

5912 def ptp(self, axis=None, out=None, fill_value=None, keepdims=False): 

5913 """ 

5914 Return (maximum - minimum) along the given dimension 

5915 (i.e. peak-to-peak value). 

5916 

5917 .. warning:: 

5918 `ptp` preserves the data type of the array. This means the 

5919 return value for an input of signed integers with n bits 

5920 (e.g. `np.int8`, `np.int16`, etc) is also a signed integer 

5921 with n bits. In that case, peak-to-peak values greater than 

5922 ``2**(n-1)-1`` will be returned as negative values. An example 

5923 with a work-around is shown below. 

5924 

5925 Parameters 

5926 ---------- 

5927 axis : {None, int}, optional 

5928 Axis along which to find the peaks. If None (default) the 

5929 flattened array is used. 

5930 out : {None, array_like}, optional 

5931 Alternative output array in which to place the result. It must 

5932 have the same shape and buffer length as the expected output 

5933 but the type will be cast if necessary. 

5934 fill_value : scalar or None, optional 

5935 Value used to fill in the masked values. 

5936 keepdims : bool, optional 

5937 If this is set to True, the axes which are reduced are left 

5938 in the result as dimensions with size one. With this option, 

5939 the result will broadcast correctly against the array. 

5940 

5941 Returns 

5942 ------- 

5943 ptp : ndarray. 

5944 A new array holding the result, unless ``out`` was 

5945 specified, in which case a reference to ``out`` is returned. 

5946 

5947 Examples 

5948 -------- 

5949 >>> x = np.ma.MaskedArray([[4, 9, 2, 10], 

5950 ... [6, 9, 7, 12]]) 

5951 

5952 >>> x.ptp(axis=1) 

5953 masked_array(data=[8, 6], 

5954 mask=False, 

5955 fill_value=999999) 

5956 

5957 >>> x.ptp(axis=0) 

5958 masked_array(data=[2, 0, 5, 2], 

5959 mask=False, 

5960 fill_value=999999) 

5961 

5962 >>> x.ptp() 

5963 10 

5964 

5965 This example shows that a negative value can be returned when 

5966 the input is an array of signed integers. 

5967 

5968 >>> y = np.ma.MaskedArray([[1, 127], 

5969 ... [0, 127], 

5970 ... [-1, 127], 

5971 ... [-2, 127]], dtype=np.int8) 

5972 >>> y.ptp(axis=1) 

5973 masked_array(data=[ 126, 127, -128, -127], 

5974 mask=False, 

5975 fill_value=999999, 

5976 dtype=int8) 

5977 

5978 A work-around is to use the `view()` method to view the result as 

5979 unsigned integers with the same bit width: 

5980 

5981 >>> y.ptp(axis=1).view(np.uint8) 

5982 masked_array(data=[126, 127, 128, 129], 

5983 mask=False, 

5984 fill_value=999999, 

5985 dtype=uint8) 

5986 """ 

5987 if out is None: 

5988 result = self.max(axis=axis, fill_value=fill_value, 

5989 keepdims=keepdims) 

5990 result -= self.min(axis=axis, fill_value=fill_value, 

5991 keepdims=keepdims) 

5992 return result 

5993 out.flat = self.max(axis=axis, out=out, fill_value=fill_value, 

5994 keepdims=keepdims) 

5995 min_value = self.min(axis=axis, fill_value=fill_value, 

5996 keepdims=keepdims) 

5997 np.subtract(out, min_value, out=out, casting='unsafe') 

5998 return out 

5999 

6000 def partition(self, *args, **kwargs): 

6001 warnings.warn("Warning: 'partition' will ignore the 'mask' " 

6002 f"of the {self.__class__.__name__}.", 

6003 stacklevel=2) 

6004 return super().partition(*args, **kwargs) 

6005 

6006 def argpartition(self, *args, **kwargs): 

6007 warnings.warn("Warning: 'argpartition' will ignore the 'mask' " 

6008 f"of the {self.__class__.__name__}.", 

6009 stacklevel=2) 

6010 return super().argpartition(*args, **kwargs) 

6011 

6012 def take(self, indices, axis=None, out=None, mode='raise'): 

6013 """ 

6014 """ 

6015 (_data, _mask) = (self._data, self._mask) 

6016 cls = type(self) 

6017 # Make sure the indices are not masked 

6018 maskindices = getmask(indices) 

6019 if maskindices is not nomask: 

6020 indices = indices.filled(0) 

6021 # Get the data, promoting scalars to 0d arrays with [...] so that 

6022 # .view works correctly 

6023 if out is None: 

6024 out = _data.take(indices, axis=axis, mode=mode)[...].view(cls) 

6025 else: 

6026 np.take(_data, indices, axis=axis, mode=mode, out=out) 

6027 # Get the mask 

6028 if isinstance(out, MaskedArray): 

6029 if _mask is nomask: 

6030 outmask = maskindices 

6031 else: 

6032 outmask = _mask.take(indices, axis=axis, mode=mode) 

6033 outmask |= maskindices 

6034 out.__setmask__(outmask) 

6035 # demote 0d arrays back to scalars, for consistency with ndarray.take 

6036 return out[()] 

6037 

6038 # Array methods 

6039 copy = _arraymethod('copy') 

6040 diagonal = _arraymethod('diagonal') 

6041 flatten = _arraymethod('flatten') 

6042 repeat = _arraymethod('repeat') 

6043 squeeze = _arraymethod('squeeze') 

6044 swapaxes = _arraymethod('swapaxes') 

6045 T = property(fget=lambda self: self.transpose()) 6045 ↛ exitline 6045 didn't run the lambda on line 6045

6046 transpose = _arraymethod('transpose') 

6047 

6048 def tolist(self, fill_value=None): 

6049 """ 

6050 Return the data portion of the masked array as a hierarchical Python list. 

6051 

6052 Data items are converted to the nearest compatible Python type. 

6053 Masked values are converted to `fill_value`. If `fill_value` is None, 

6054 the corresponding entries in the output list will be ``None``. 

6055 

6056 Parameters 

6057 ---------- 

6058 fill_value : scalar, optional 

6059 The value to use for invalid entries. Default is None. 

6060 

6061 Returns 

6062 ------- 

6063 result : list 

6064 The Python list representation of the masked array. 

6065 

6066 Examples 

6067 -------- 

6068 >>> x = np.ma.array([[1,2,3], [4,5,6], [7,8,9]], mask=[0] + [1,0]*4) 

6069 >>> x.tolist() 

6070 [[1, None, 3], [None, 5, None], [7, None, 9]] 

6071 >>> x.tolist(-999) 

6072 [[1, -999, 3], [-999, 5, -999], [7, -999, 9]] 

6073 

6074 """ 

6075 _mask = self._mask 

6076 # No mask ? Just return .data.tolist ? 

6077 if _mask is nomask: 

6078 return self._data.tolist() 

6079 # Explicit fill_value: fill the array and get the list 

6080 if fill_value is not None: 

6081 return self.filled(fill_value).tolist() 

6082 # Structured array. 

6083 names = self.dtype.names 

6084 if names: 

6085 result = self._data.astype([(_, object) for _ in names]) 

6086 for n in names: 

6087 result[n][_mask[n]] = None 

6088 return result.tolist() 

6089 # Standard arrays. 

6090 if _mask is nomask: 

6091 return [None] 

6092 # Set temps to save time when dealing w/ marrays. 

6093 inishape = self.shape 

6094 result = np.array(self._data.ravel(), dtype=object) 

6095 result[_mask.ravel()] = None 

6096 result.shape = inishape 

6097 return result.tolist() 

6098 

6099 def tostring(self, fill_value=None, order='C'): 

6100 r""" 

6101 A compatibility alias for `tobytes`, with exactly the same behavior. 

6102 

6103 Despite its name, it returns `bytes` not `str`\ s. 

6104 

6105 .. deprecated:: 1.19.0 

6106 """ 

6107 # 2020-03-30, Numpy 1.19.0 

6108 warnings.warn( 

6109 "tostring() is deprecated. Use tobytes() instead.", 

6110 DeprecationWarning, stacklevel=2) 

6111 

6112 return self.tobytes(fill_value, order=order) 

6113 

6114 def tobytes(self, fill_value=None, order='C'): 

6115 """ 

6116 Return the array data as a string containing the raw bytes in the array. 

6117 

6118 The array is filled with a fill value before the string conversion. 

6119 

6120 .. versionadded:: 1.9.0 

6121 

6122 Parameters 

6123 ---------- 

6124 fill_value : scalar, optional 

6125 Value used to fill in the masked values. Default is None, in which 

6126 case `MaskedArray.fill_value` is used. 

6127 order : {'C','F','A'}, optional 

6128 Order of the data item in the copy. Default is 'C'. 

6129 

6130 - 'C' -- C order (row major). 

6131 - 'F' -- Fortran order (column major). 

6132 - 'A' -- Any, current order of array. 

6133 - None -- Same as 'A'. 

6134 

6135 See Also 

6136 -------- 

6137 numpy.ndarray.tobytes 

6138 tolist, tofile 

6139 

6140 Notes 

6141 ----- 

6142 As for `ndarray.tobytes`, information about the shape, dtype, etc., 

6143 but also about `fill_value`, will be lost. 

6144 

6145 Examples 

6146 -------- 

6147 >>> x = np.ma.array(np.array([[1, 2], [3, 4]]), mask=[[0, 1], [1, 0]]) 

6148 >>> x.tobytes() 

6149 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' 

6150 

6151 """ 

6152 return self.filled(fill_value).tobytes(order=order) 

6153 

6154 def tofile(self, fid, sep="", format="%s"): 

6155 """ 

6156 Save a masked array to a file in binary format. 

6157 

6158 .. warning:: 

6159 This function is not implemented yet. 

6160 

6161 Raises 

6162 ------ 

6163 NotImplementedError 

6164 When `tofile` is called. 

6165 

6166 """ 

6167 raise NotImplementedError("MaskedArray.tofile() not implemented yet.") 

6168 

6169 def toflex(self): 

6170 """ 

6171 Transforms a masked array into a flexible-type array. 

6172 

6173 The flexible type array that is returned will have two fields: 

6174 

6175 * the ``_data`` field stores the ``_data`` part of the array. 

6176 * the ``_mask`` field stores the ``_mask`` part of the array. 

6177 

6178 Parameters 

6179 ---------- 

6180 None 

6181 

6182 Returns 

6183 ------- 

6184 record : ndarray 

6185 A new flexible-type `ndarray` with two fields: the first element 

6186 containing a value, the second element containing the corresponding 

6187 mask boolean. The returned record shape matches self.shape. 

6188 

6189 Notes 

6190 ----- 

6191 A side-effect of transforming a masked array into a flexible `ndarray` is 

6192 that meta information (``fill_value``, ...) will be lost. 

6193 

6194 Examples 

6195 -------- 

6196 >>> x = np.ma.array([[1,2,3],[4,5,6],[7,8,9]], mask=[0] + [1,0]*4) 

6197 >>> x 

6198 masked_array( 

6199 data=[[1, --, 3], 

6200 [--, 5, --], 

6201 [7, --, 9]], 

6202 mask=[[False, True, False], 

6203 [ True, False, True], 

6204 [False, True, False]], 

6205 fill_value=999999) 

6206 >>> x.toflex() 

6207 array([[(1, False), (2, True), (3, False)], 

6208 [(4, True), (5, False), (6, True)], 

6209 [(7, False), (8, True), (9, False)]], 

6210 dtype=[('_data', '<i8'), ('_mask', '?')]) 

6211 

6212 """ 

6213 # Get the basic dtype. 

6214 ddtype = self.dtype 

6215 # Make sure we have a mask 

6216 _mask = self._mask 

6217 if _mask is None: 

6218 _mask = make_mask_none(self.shape, ddtype) 

6219 # And get its dtype 

6220 mdtype = self._mask.dtype 

6221 

6222 record = np.ndarray(shape=self.shape, 

6223 dtype=[('_data', ddtype), ('_mask', mdtype)]) 

6224 record['_data'] = self._data 

6225 record['_mask'] = self._mask 

6226 return record 

6227 torecords = toflex 

6228 

6229 # Pickling 

6230 def __getstate__(self): 

6231 """Return the internal state of the masked array, for pickling 

6232 purposes. 

6233 

6234 """ 

6235 cf = 'CF'[self.flags.fnc] 

6236 data_state = super().__reduce__()[2] 

6237 return data_state + (getmaskarray(self).tobytes(cf), self._fill_value) 

6238 

6239 def __setstate__(self, state): 

6240 """Restore the internal state of the masked array, for 

6241 pickling purposes. ``state`` is typically the output of the 

6242 ``__getstate__`` output, and is a 5-tuple: 

6243 

6244 - class name 

6245 - a tuple giving the shape of the data 

6246 - a typecode for the data 

6247 - a binary string for the data 

6248 - a binary string for the mask. 

6249 

6250 """ 

6251 (_, shp, typ, isf, raw, msk, flv) = state 

6252 super().__setstate__((shp, typ, isf, raw)) 

6253 self._mask.__setstate__((shp, make_mask_descr(typ), isf, msk)) 

6254 self.fill_value = flv 

6255 

6256 def __reduce__(self): 

6257 """Return a 3-tuple for pickling a MaskedArray. 

6258 

6259 """ 

6260 return (_mareconstruct, 

6261 (self.__class__, self._baseclass, (0,), 'b',), 

6262 self.__getstate__()) 

6263 

6264 def __deepcopy__(self, memo=None): 

6265 from copy import deepcopy 

6266 copied = MaskedArray.__new__(type(self), self, copy=True) 

6267 if memo is None: 

6268 memo = {} 

6269 memo[id(self)] = copied 

6270 for (k, v) in self.__dict__.items(): 

6271 copied.__dict__[k] = deepcopy(v, memo) 

6272 return copied 

6273 

6274 

6275def _mareconstruct(subtype, baseclass, baseshape, basetype,): 

6276 """Internal function that builds a new MaskedArray from the 

6277 information stored in a pickle. 

6278 

6279 """ 

6280 _data = ndarray.__new__(baseclass, baseshape, basetype) 

6281 _mask = ndarray.__new__(ndarray, baseshape, make_mask_descr(basetype)) 

6282 return subtype.__new__(subtype, _data, mask=_mask, dtype=basetype,) 

6283 

6284 

6285class mvoid(MaskedArray): 

6286 """ 

6287 Fake a 'void' object to use for masked array with structured dtypes. 

6288 """ 

6289 

6290 def __new__(self, data, mask=nomask, dtype=None, fill_value=None, 

6291 hardmask=False, copy=False, subok=True): 

6292 _data = np.array(data, copy=copy, subok=subok, dtype=dtype) 

6293 _data = _data.view(self) 

6294 _data._hardmask = hardmask 

6295 if mask is not nomask: 

6296 if isinstance(mask, np.void): 

6297 _data._mask = mask 

6298 else: 

6299 try: 

6300 # Mask is already a 0D array 

6301 _data._mask = np.void(mask) 

6302 except TypeError: 

6303 # Transform the mask to a void 

6304 mdtype = make_mask_descr(dtype) 

6305 _data._mask = np.array(mask, dtype=mdtype)[()] 

6306 if fill_value is not None: 

6307 _data.fill_value = fill_value 

6308 return _data 

6309 

6310 @property 

6311 def _data(self): 

6312 # Make sure that the _data part is a np.void 

6313 return super()._data[()] 

6314 

6315 def __getitem__(self, indx): 

6316 """ 

6317 Get the index. 

6318 

6319 """ 

6320 m = self._mask 

6321 if isinstance(m[indx], ndarray): 

6322 # Can happen when indx is a multi-dimensional field: 

6323 # A = ma.masked_array(data=[([0,1],)], mask=[([True, 

6324 # False],)], dtype=[("A", ">i2", (2,))]) 

6325 # x = A[0]; y = x["A"]; then y.mask["A"].size==2 

6326 # and we can not say masked/unmasked. 

6327 # The result is no longer mvoid! 

6328 # See also issue #6724. 

6329 return masked_array( 

6330 data=self._data[indx], mask=m[indx], 

6331 fill_value=self._fill_value[indx], 

6332 hard_mask=self._hardmask) 

6333 if m is not nomask and m[indx]: 

6334 return masked 

6335 return self._data[indx] 

6336 

6337 def __setitem__(self, indx, value): 

6338 self._data[indx] = value 

6339 if self._hardmask: 

6340 self._mask[indx] |= getattr(value, "_mask", False) 

6341 else: 

6342 self._mask[indx] = getattr(value, "_mask", False) 

6343 

6344 def __str__(self): 

6345 m = self._mask 

6346 if m is nomask: 

6347 return str(self._data) 

6348 

6349 rdtype = _replace_dtype_fields(self._data.dtype, "O") 

6350 data_arr = super()._data 

6351 res = data_arr.astype(rdtype) 

6352 _recursive_printoption(res, self._mask, masked_print_option) 

6353 return str(res) 

6354 

6355 __repr__ = __str__ 

6356 

6357 def __iter__(self): 

6358 "Defines an iterator for mvoid" 

6359 (_data, _mask) = (self._data, self._mask) 

6360 if _mask is nomask: 

6361 yield from _data 

6362 else: 

6363 for (d, m) in zip(_data, _mask): 

6364 if m: 

6365 yield masked 

6366 else: 

6367 yield d 

6368 

6369 def __len__(self): 

6370 return self._data.__len__() 

6371 

6372 def filled(self, fill_value=None): 

6373 """ 

6374 Return a copy with masked fields filled with a given value. 

6375 

6376 Parameters 

6377 ---------- 

6378 fill_value : array_like, optional 

6379 The value to use for invalid entries. Can be scalar or 

6380 non-scalar. If latter is the case, the filled array should 

6381 be broadcastable over input array. Default is None, in 

6382 which case the `fill_value` attribute is used instead. 

6383 

6384 Returns 

6385 ------- 

6386 filled_void 

6387 A `np.void` object 

6388 

6389 See Also 

6390 -------- 

6391 MaskedArray.filled 

6392 

6393 """ 

6394 return asarray(self).filled(fill_value)[()] 

6395 

6396 def tolist(self): 

6397 """ 

6398 Transforms the mvoid object into a tuple. 

6399 

6400 Masked fields are replaced by None. 

6401 

6402 Returns 

6403 ------- 

6404 returned_tuple 

6405 Tuple of fields 

6406 """ 

6407 _mask = self._mask 

6408 if _mask is nomask: 

6409 return self._data.tolist() 

6410 result = [] 

6411 for (d, m) in zip(self._data, self._mask): 

6412 if m: 

6413 result.append(None) 

6414 else: 

6415 # .item() makes sure we return a standard Python object 

6416 result.append(d.item()) 

6417 return tuple(result) 

6418 

6419 

6420############################################################################## 

6421# Shortcuts # 

6422############################################################################## 

6423 

6424 

6425def isMaskedArray(x): 

6426 """ 

6427 Test whether input is an instance of MaskedArray. 

6428 

6429 This function returns True if `x` is an instance of MaskedArray 

6430 and returns False otherwise. Any object is accepted as input. 

6431 

6432 Parameters 

6433 ---------- 

6434 x : object 

6435 Object to test. 

6436 

6437 Returns 

6438 ------- 

6439 result : bool 

6440 True if `x` is a MaskedArray. 

6441 

6442 See Also 

6443 -------- 

6444 isMA : Alias to isMaskedArray. 

6445 isarray : Alias to isMaskedArray. 

6446 

6447 Examples 

6448 -------- 

6449 >>> import numpy.ma as ma 

6450 >>> a = np.eye(3, 3) 

6451 >>> a 

6452 array([[ 1., 0., 0.], 

6453 [ 0., 1., 0.], 

6454 [ 0., 0., 1.]]) 

6455 >>> m = ma.masked_values(a, 0) 

6456 >>> m 

6457 masked_array( 

6458 data=[[1.0, --, --], 

6459 [--, 1.0, --], 

6460 [--, --, 1.0]], 

6461 mask=[[False, True, True], 

6462 [ True, False, True], 

6463 [ True, True, False]], 

6464 fill_value=0.0) 

6465 >>> ma.isMaskedArray(a) 

6466 False 

6467 >>> ma.isMaskedArray(m) 

6468 True 

6469 >>> ma.isMaskedArray([0, 1, 2]) 

6470 False 

6471 

6472 """ 

6473 return isinstance(x, MaskedArray) 

6474 

6475 

6476isarray = isMaskedArray 

6477isMA = isMaskedArray # backward compatibility 

6478 

6479 

6480class MaskedConstant(MaskedArray): 

6481 # the lone np.ma.masked instance 

6482 __singleton = None 

6483 

6484 @classmethod 

6485 def __has_singleton(cls): 

6486 # second case ensures `cls.__singleton` is not just a view on the 

6487 # superclass singleton 

6488 return cls.__singleton is not None and type(cls.__singleton) is cls 

6489 

6490 def __new__(cls): 

6491 if not cls.__has_singleton(): 6491 ↛ 6506line 6491 didn't jump to line 6506, because the condition on line 6491 was never false

6492 # We define the masked singleton as a float for higher precedence. 

6493 # Note that it can be tricky sometimes w/ type comparison 

6494 data = np.array(0.) 

6495 mask = np.array(True) 

6496 

6497 # prevent any modifications 

6498 data.flags.writeable = False 

6499 mask.flags.writeable = False 

6500 

6501 # don't fall back on MaskedArray.__new__(MaskedConstant), since 

6502 # that might confuse it - this way, the construction is entirely 

6503 # within our control 

6504 cls.__singleton = MaskedArray(data, mask=mask).view(cls) 

6505 

6506 return cls.__singleton 

6507 

6508 def __array_finalize__(self, obj): 

6509 if not self.__has_singleton(): 6509 ↛ 6513line 6509 didn't jump to line 6513, because the condition on line 6509 was never false

6510 # this handles the `.view` in __new__, which we want to copy across 

6511 # properties normally 

6512 return super().__array_finalize__(obj) 

6513 elif self is self.__singleton: 

6514 # not clear how this can happen, play it safe 

6515 pass 

6516 else: 

6517 # everywhere else, we want to downcast to MaskedArray, to prevent a 

6518 # duplicate maskedconstant. 

6519 self.__class__ = MaskedArray 

6520 MaskedArray.__array_finalize__(self, obj) 

6521 

6522 def __array_prepare__(self, obj, context=None): 

6523 return self.view(MaskedArray).__array_prepare__(obj, context) 

6524 

6525 def __array_wrap__(self, obj, context=None): 

6526 return self.view(MaskedArray).__array_wrap__(obj, context) 

6527 

6528 def __str__(self): 

6529 return str(masked_print_option._display) 

6530 

6531 def __repr__(self): 

6532 if self is MaskedConstant.__singleton: 

6533 return 'masked' 

6534 else: 

6535 # it's a subclass, or something is wrong, make it obvious 

6536 return object.__repr__(self) 

6537 

6538 def __format__(self, format_spec): 

6539 # Replace ndarray.__format__ with the default, which supports no format characters. 

6540 # Supporting format characters is unwise here, because we do not know what type 

6541 # the user was expecting - better to not guess. 

6542 try: 

6543 return object.__format__(self, format_spec) 

6544 except TypeError: 

6545 # 2020-03-23, NumPy 1.19.0 

6546 warnings.warn( 

6547 "Format strings passed to MaskedConstant are ignored, but in future may " 

6548 "error or produce different behavior", 

6549 FutureWarning, stacklevel=2 

6550 ) 

6551 return object.__format__(self, "") 

6552 

6553 def __reduce__(self): 

6554 """Override of MaskedArray's __reduce__. 

6555 """ 

6556 return (self.__class__, ()) 

6557 

6558 # inplace operations have no effect. We have to override them to avoid 

6559 # trying to modify the readonly data and mask arrays 

6560 def __iop__(self, other): 

6561 return self 

6562 __iadd__ = \ 

6563 __isub__ = \ 

6564 __imul__ = \ 

6565 __ifloordiv__ = \ 

6566 __itruediv__ = \ 

6567 __ipow__ = \ 

6568 __iop__ 

6569 del __iop__ # don't leave this around 

6570 

6571 def copy(self, *args, **kwargs): 

6572 """ Copy is a no-op on the maskedconstant, as it is a scalar """ 

6573 # maskedconstant is a scalar, so copy doesn't need to copy. There's 

6574 # precedent for this with `np.bool_` scalars. 

6575 return self 

6576 

6577 def __copy__(self): 

6578 return self 

6579 

6580 def __deepcopy__(self, memo): 

6581 return self 

6582 

6583 def __setattr__(self, attr, value): 

6584 if not self.__has_singleton(): 6584 ↛ 6587line 6584 didn't jump to line 6587, because the condition on line 6584 was never false

6585 # allow the singleton to be initialized 

6586 return super().__setattr__(attr, value) 

6587 elif self is self.__singleton: 

6588 raise AttributeError( 

6589 f"attributes of {self!r} are not writeable") 

6590 else: 

6591 # duplicate instance - we can end up here from __array_finalize__, 

6592 # where we set the __class__ attribute 

6593 return super().__setattr__(attr, value) 

6594 

6595 

6596masked = masked_singleton = MaskedConstant() 

6597masked_array = MaskedArray 

6598 

6599 

6600def array(data, dtype=None, copy=False, order=None, 

6601 mask=nomask, fill_value=None, keep_mask=True, 

6602 hard_mask=False, shrink=True, subok=True, ndmin=0): 

6603 """ 

6604 Shortcut to MaskedArray. 

6605 

6606 The options are in a different order for convenience and backwards 

6607 compatibility. 

6608 

6609 """ 

6610 return MaskedArray(data, mask=mask, dtype=dtype, copy=copy, 

6611 subok=subok, keep_mask=keep_mask, 

6612 hard_mask=hard_mask, fill_value=fill_value, 

6613 ndmin=ndmin, shrink=shrink, order=order) 

6614array.__doc__ = masked_array.__doc__ 

6615 

6616 

6617def is_masked(x): 

6618 """ 

6619 Determine whether input has masked values. 

6620 

6621 Accepts any object as input, but always returns False unless the 

6622 input is a MaskedArray containing masked values. 

6623 

6624 Parameters 

6625 ---------- 

6626 x : array_like 

6627 Array to check for masked values. 

6628 

6629 Returns 

6630 ------- 

6631 result : bool 

6632 True if `x` is a MaskedArray with masked values, False otherwise. 

6633 

6634 Examples 

6635 -------- 

6636 >>> import numpy.ma as ma 

6637 >>> x = ma.masked_equal([0, 1, 0, 2, 3], 0) 

6638 >>> x 

6639 masked_array(data=[--, 1, --, 2, 3], 

6640 mask=[ True, False, True, False, False], 

6641 fill_value=0) 

6642 >>> ma.is_masked(x) 

6643 True 

6644 >>> x = ma.masked_equal([0, 1, 0, 2, 3], 42) 

6645 >>> x 

6646 masked_array(data=[0, 1, 0, 2, 3], 

6647 mask=False, 

6648 fill_value=42) 

6649 >>> ma.is_masked(x) 

6650 False 

6651 

6652 Always returns False if `x` isn't a MaskedArray. 

6653 

6654 >>> x = [False, True, False] 

6655 >>> ma.is_masked(x) 

6656 False 

6657 >>> x = 'a string' 

6658 >>> ma.is_masked(x) 

6659 False 

6660 

6661 """ 

6662 m = getmask(x) 

6663 if m is nomask: 

6664 return False 

6665 elif m.any(): 

6666 return True 

6667 return False 

6668 

6669 

6670############################################################################## 

6671# Extrema functions # 

6672############################################################################## 

6673 

6674 

6675class _extrema_operation(_MaskedUFunc): 

6676 """ 

6677 Generic class for maximum/minimum functions. 

6678 

6679 .. note:: 

6680 This is the base class for `_maximum_operation` and 

6681 `_minimum_operation`. 

6682 

6683 """ 

6684 def __init__(self, ufunc, compare, fill_value): 

6685 super().__init__(ufunc) 

6686 self.compare = compare 

6687 self.fill_value_func = fill_value 

6688 

6689 def __call__(self, a, b=None): 

6690 "Executes the call behavior." 

6691 if b is None: 

6692 # 2016-04-13, 1.13.0 

6693 warnings.warn( 

6694 f"Single-argument form of np.ma.{self.__name__} is deprecated. Use " 

6695 f"np.ma.{self.__name__}.reduce instead.", 

6696 DeprecationWarning, stacklevel=2) 

6697 return self.reduce(a) 

6698 return where(self.compare(a, b), a, b) 

6699 

6700 def reduce(self, target, axis=np._NoValue): 

6701 "Reduce target along the given axis." 

6702 target = narray(target, copy=False, subok=True) 

6703 m = getmask(target) 

6704 

6705 if axis is np._NoValue and target.ndim > 1: 

6706 # 2017-05-06, Numpy 1.13.0: warn on axis default 

6707 warnings.warn( 

6708 f"In the future the default for ma.{self.__name__}.reduce will be axis=0, " 

6709 f"not the current None, to match np.{self.__name__}.reduce. " 

6710 "Explicitly pass 0 or None to silence this warning.", 

6711 MaskedArrayFutureWarning, stacklevel=2) 

6712 axis = None 

6713 

6714 if axis is not np._NoValue: 

6715 kwargs = dict(axis=axis) 

6716 else: 

6717 kwargs = dict() 

6718 

6719 if m is nomask: 

6720 t = self.f.reduce(target, **kwargs) 

6721 else: 

6722 target = target.filled( 

6723 self.fill_value_func(target)).view(type(target)) 

6724 t = self.f.reduce(target, **kwargs) 

6725 m = umath.logical_and.reduce(m, **kwargs) 

6726 if hasattr(t, '_mask'): 

6727 t._mask = m 

6728 elif m: 

6729 t = masked 

6730 return t 

6731 

6732 def outer(self, a, b): 

6733 "Return the function applied to the outer product of a and b." 

6734 ma = getmask(a) 

6735 mb = getmask(b) 

6736 if ma is nomask and mb is nomask: 

6737 m = nomask 

6738 else: 

6739 ma = getmaskarray(a) 

6740 mb = getmaskarray(b) 

6741 m = logical_or.outer(ma, mb) 

6742 result = self.f.outer(filled(a), filled(b)) 

6743 if not isinstance(result, MaskedArray): 

6744 result = result.view(MaskedArray) 

6745 result._mask = m 

6746 return result 

6747 

6748def min(obj, axis=None, out=None, fill_value=None, keepdims=np._NoValue): 

6749 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

6750 

6751 try: 

6752 return obj.min(axis=axis, fill_value=fill_value, out=out, **kwargs) 

6753 except (AttributeError, TypeError): 

6754 # If obj doesn't have a min method, or if the method doesn't accept a 

6755 # fill_value argument 

6756 return asanyarray(obj).min(axis=axis, fill_value=fill_value, 

6757 out=out, **kwargs) 

6758min.__doc__ = MaskedArray.min.__doc__ 

6759 

6760def max(obj, axis=None, out=None, fill_value=None, keepdims=np._NoValue): 

6761 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

6762 

6763 try: 

6764 return obj.max(axis=axis, fill_value=fill_value, out=out, **kwargs) 

6765 except (AttributeError, TypeError): 

6766 # If obj doesn't have a max method, or if the method doesn't accept a 

6767 # fill_value argument 

6768 return asanyarray(obj).max(axis=axis, fill_value=fill_value, 

6769 out=out, **kwargs) 

6770max.__doc__ = MaskedArray.max.__doc__ 

6771 

6772 

6773def ptp(obj, axis=None, out=None, fill_value=None, keepdims=np._NoValue): 

6774 kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

6775 try: 

6776 return obj.ptp(axis, out=out, fill_value=fill_value, **kwargs) 

6777 except (AttributeError, TypeError): 

6778 # If obj doesn't have a ptp method or if the method doesn't accept 

6779 # a fill_value argument 

6780 return asanyarray(obj).ptp(axis=axis, fill_value=fill_value, 

6781 out=out, **kwargs) 

6782ptp.__doc__ = MaskedArray.ptp.__doc__ 

6783 

6784 

6785############################################################################## 

6786# Definition of functions from the corresponding methods # 

6787############################################################################## 

6788 

6789 

6790class _frommethod: 

6791 """ 

6792 Define functions from existing MaskedArray methods. 

6793 

6794 Parameters 

6795 ---------- 

6796 methodname : str 

6797 Name of the method to transform. 

6798 

6799 """ 

6800 

6801 def __init__(self, methodname, reversed=False): 

6802 self.__name__ = methodname 

6803 self.__doc__ = self.getdoc() 

6804 self.reversed = reversed 

6805 

6806 def getdoc(self): 

6807 "Return the doc of the function (from the doc of the method)." 

6808 meth = getattr(MaskedArray, self.__name__, None) or\ 

6809 getattr(np, self.__name__, None) 

6810 signature = self.__name__ + get_object_signature(meth) 

6811 if meth is not None: 6811 ↛ exitline 6811 didn't return from function 'getdoc', because the condition on line 6811 was never false

6812 doc = """ %s\n%s""" % ( 

6813 signature, getattr(meth, '__doc__', None)) 

6814 return doc 

6815 

6816 def __call__(self, a, *args, **params): 

6817 if self.reversed: 

6818 args = list(args) 

6819 a, args[0] = args[0], a 

6820 

6821 marr = asanyarray(a) 

6822 method_name = self.__name__ 

6823 method = getattr(type(marr), method_name, None) 

6824 if method is None: 

6825 # use the corresponding np function 

6826 method = getattr(np, method_name) 

6827 

6828 return method(marr, *args, **params) 

6829 

6830 

6831all = _frommethod('all') 

6832anomalies = anom = _frommethod('anom') 

6833any = _frommethod('any') 

6834compress = _frommethod('compress', reversed=True) 

6835cumprod = _frommethod('cumprod') 

6836cumsum = _frommethod('cumsum') 

6837copy = _frommethod('copy') 

6838diagonal = _frommethod('diagonal') 

6839harden_mask = _frommethod('harden_mask') 

6840ids = _frommethod('ids') 

6841maximum = _extrema_operation(umath.maximum, greater, maximum_fill_value) 

6842mean = _frommethod('mean') 

6843minimum = _extrema_operation(umath.minimum, less, minimum_fill_value) 

6844nonzero = _frommethod('nonzero') 

6845prod = _frommethod('prod') 

6846product = _frommethod('prod') 

6847ravel = _frommethod('ravel') 

6848repeat = _frommethod('repeat') 

6849shrink_mask = _frommethod('shrink_mask') 

6850soften_mask = _frommethod('soften_mask') 

6851std = _frommethod('std') 

6852sum = _frommethod('sum') 

6853swapaxes = _frommethod('swapaxes') 

6854#take = _frommethod('take') 

6855trace = _frommethod('trace') 

6856var = _frommethod('var') 

6857 

6858count = _frommethod('count') 

6859 

6860def take(a, indices, axis=None, out=None, mode='raise'): 

6861 """ 

6862 """ 

6863 a = masked_array(a) 

6864 return a.take(indices, axis=axis, out=out, mode=mode) 

6865 

6866 

6867def power(a, b, third=None): 

6868 """ 

6869 Returns element-wise base array raised to power from second array. 

6870 

6871 This is the masked array version of `numpy.power`. For details see 

6872 `numpy.power`. 

6873 

6874 See Also 

6875 -------- 

6876 numpy.power 

6877 

6878 Notes 

6879 ----- 

6880 The *out* argument to `numpy.power` is not supported, `third` has to be 

6881 None. 

6882 

6883 """ 

6884 if third is not None: 

6885 raise MaskError("3-argument power not supported.") 

6886 # Get the masks 

6887 ma = getmask(a) 

6888 mb = getmask(b) 

6889 m = mask_or(ma, mb) 

6890 # Get the rawdata 

6891 fa = getdata(a) 

6892 fb = getdata(b) 

6893 # Get the type of the result (so that we preserve subclasses) 

6894 if isinstance(a, MaskedArray): 

6895 basetype = type(a) 

6896 else: 

6897 basetype = MaskedArray 

6898 # Get the result and view it as a (subclass of) MaskedArray 

6899 with np.errstate(divide='ignore', invalid='ignore'): 

6900 result = np.where(m, fa, umath.power(fa, fb)).view(basetype) 

6901 result._update_from(a) 

6902 # Find where we're in trouble w/ NaNs and Infs 

6903 invalid = np.logical_not(np.isfinite(result.view(ndarray))) 

6904 # Add the initial mask 

6905 if m is not nomask: 

6906 if not result.ndim: 

6907 return masked 

6908 result._mask = np.logical_or(m, invalid) 

6909 # Fix the invalid parts 

6910 if invalid.any(): 

6911 if not result.ndim: 

6912 return masked 

6913 elif result._mask is nomask: 

6914 result._mask = invalid 

6915 result._data[invalid] = result.fill_value 

6916 return result 

6917 

6918argmin = _frommethod('argmin') 

6919argmax = _frommethod('argmax') 

6920 

6921def argsort(a, axis=np._NoValue, kind=None, order=None, endwith=True, fill_value=None): 

6922 "Function version of the eponymous method." 

6923 a = np.asanyarray(a) 

6924 

6925 # 2017-04-11, Numpy 1.13.0, gh-8701: warn on axis default 

6926 if axis is np._NoValue: 

6927 axis = _deprecate_argsort_axis(a) 

6928 

6929 if isinstance(a, MaskedArray): 

6930 return a.argsort(axis=axis, kind=kind, order=order, 

6931 endwith=endwith, fill_value=fill_value) 

6932 else: 

6933 return a.argsort(axis=axis, kind=kind, order=order) 

6934argsort.__doc__ = MaskedArray.argsort.__doc__ 

6935 

6936def sort(a, axis=-1, kind=None, order=None, endwith=True, fill_value=None): 

6937 """ 

6938 Return a sorted copy of the masked array. 

6939 

6940 Equivalent to creating a copy of the array 

6941 and applying the MaskedArray ``sort()`` method. 

6942 

6943 Refer to ``MaskedArray.sort`` for the full documentation 

6944 

6945 See Also 

6946 -------- 

6947 MaskedArray.sort : equivalent method 

6948 """ 

6949 a = np.array(a, copy=True, subok=True) 

6950 if axis is None: 

6951 a = a.flatten() 

6952 axis = 0 

6953 

6954 if isinstance(a, MaskedArray): 

6955 a.sort(axis=axis, kind=kind, order=order, 

6956 endwith=endwith, fill_value=fill_value) 

6957 else: 

6958 a.sort(axis=axis, kind=kind, order=order) 

6959 return a 

6960 

6961 

6962def compressed(x): 

6963 """ 

6964 Return all the non-masked data as a 1-D array. 

6965 

6966 This function is equivalent to calling the "compressed" method of a 

6967 `ma.MaskedArray`, see `ma.MaskedArray.compressed` for details. 

6968 

6969 See Also 

6970 -------- 

6971 ma.MaskedArray.compressed : Equivalent method. 

6972 

6973 """ 

6974 return asanyarray(x).compressed() 

6975 

6976 

6977def concatenate(arrays, axis=0): 

6978 """ 

6979 Concatenate a sequence of arrays along the given axis. 

6980 

6981 Parameters 

6982 ---------- 

6983 arrays : sequence of array_like 

6984 The arrays must have the same shape, except in the dimension 

6985 corresponding to `axis` (the first, by default). 

6986 axis : int, optional 

6987 The axis along which the arrays will be joined. Default is 0. 

6988 

6989 Returns 

6990 ------- 

6991 result : MaskedArray 

6992 The concatenated array with any masked entries preserved. 

6993 

6994 See Also 

6995 -------- 

6996 numpy.concatenate : Equivalent function in the top-level NumPy module. 

6997 

6998 Examples 

6999 -------- 

7000 >>> import numpy.ma as ma 

7001 >>> a = ma.arange(3) 

7002 >>> a[1] = ma.masked 

7003 >>> b = ma.arange(2, 5) 

7004 >>> a 

7005 masked_array(data=[0, --, 2], 

7006 mask=[False, True, False], 

7007 fill_value=999999) 

7008 >>> b 

7009 masked_array(data=[2, 3, 4], 

7010 mask=False, 

7011 fill_value=999999) 

7012 >>> ma.concatenate([a, b]) 

7013 masked_array(data=[0, --, 2, 2, 3, 4], 

7014 mask=[False, True, False, False, False, False], 

7015 fill_value=999999) 

7016 

7017 """ 

7018 d = np.concatenate([getdata(a) for a in arrays], axis) 

7019 rcls = get_masked_subclass(*arrays) 

7020 data = d.view(rcls) 

7021 # Check whether one of the arrays has a non-empty mask. 

7022 for x in arrays: 

7023 if getmask(x) is not nomask: 

7024 break 

7025 else: 

7026 return data 

7027 # OK, so we have to concatenate the masks 

7028 dm = np.concatenate([getmaskarray(a) for a in arrays], axis) 

7029 dm = dm.reshape(d.shape) 

7030 

7031 # If we decide to keep a '_shrinkmask' option, we want to check that 

7032 # all of them are True, and then check for dm.any() 

7033 data._mask = _shrink_mask(dm) 

7034 return data 

7035 

7036 

7037def diag(v, k=0): 

7038 """ 

7039 Extract a diagonal or construct a diagonal array. 

7040 

7041 This function is the equivalent of `numpy.diag` that takes masked 

7042 values into account, see `numpy.diag` for details. 

7043 

7044 See Also 

7045 -------- 

7046 numpy.diag : Equivalent function for ndarrays. 

7047 

7048 """ 

7049 output = np.diag(v, k).view(MaskedArray) 

7050 if getmask(v) is not nomask: 

7051 output._mask = np.diag(v._mask, k) 

7052 return output 

7053 

7054 

7055def left_shift(a, n): 

7056 """ 

7057 Shift the bits of an integer to the left. 

7058 

7059 This is the masked array version of `numpy.left_shift`, for details 

7060 see that function. 

7061 

7062 See Also 

7063 -------- 

7064 numpy.left_shift 

7065 

7066 """ 

7067 m = getmask(a) 

7068 if m is nomask: 

7069 d = umath.left_shift(filled(a), n) 

7070 return masked_array(d) 

7071 else: 

7072 d = umath.left_shift(filled(a, 0), n) 

7073 return masked_array(d, mask=m) 

7074 

7075 

7076def right_shift(a, n): 

7077 """ 

7078 Shift the bits of an integer to the right. 

7079 

7080 This is the masked array version of `numpy.right_shift`, for details 

7081 see that function. 

7082 

7083 See Also 

7084 -------- 

7085 numpy.right_shift 

7086 

7087 """ 

7088 m = getmask(a) 

7089 if m is nomask: 

7090 d = umath.right_shift(filled(a), n) 

7091 return masked_array(d) 

7092 else: 

7093 d = umath.right_shift(filled(a, 0), n) 

7094 return masked_array(d, mask=m) 

7095 

7096 

7097def put(a, indices, values, mode='raise'): 

7098 """ 

7099 Set storage-indexed locations to corresponding values. 

7100 

7101 This function is equivalent to `MaskedArray.put`, see that method 

7102 for details. 

7103 

7104 See Also 

7105 -------- 

7106 MaskedArray.put 

7107 

7108 """ 

7109 # We can't use 'frommethod', the order of arguments is different 

7110 try: 

7111 return a.put(indices, values, mode=mode) 

7112 except AttributeError: 

7113 return narray(a, copy=False).put(indices, values, mode=mode) 

7114 

7115 

7116def putmask(a, mask, values): # , mode='raise'): 

7117 """ 

7118 Changes elements of an array based on conditional and input values. 

7119 

7120 This is the masked array version of `numpy.putmask`, for details see 

7121 `numpy.putmask`. 

7122 

7123 See Also 

7124 -------- 

7125 numpy.putmask 

7126 

7127 Notes 

7128 ----- 

7129 Using a masked array as `values` will **not** transform a `ndarray` into 

7130 a `MaskedArray`. 

7131 

7132 """ 

7133 # We can't use 'frommethod', the order of arguments is different 

7134 if not isinstance(a, MaskedArray): 

7135 a = a.view(MaskedArray) 

7136 (valdata, valmask) = (getdata(values), getmask(values)) 

7137 if getmask(a) is nomask: 

7138 if valmask is not nomask: 

7139 a._sharedmask = True 

7140 a._mask = make_mask_none(a.shape, a.dtype) 

7141 np.copyto(a._mask, valmask, where=mask) 

7142 elif a._hardmask: 

7143 if valmask is not nomask: 

7144 m = a._mask.copy() 

7145 np.copyto(m, valmask, where=mask) 

7146 a.mask |= m 

7147 else: 

7148 if valmask is nomask: 

7149 valmask = getmaskarray(values) 

7150 np.copyto(a._mask, valmask, where=mask) 

7151 np.copyto(a._data, valdata, where=mask) 

7152 return 

7153 

7154 

7155def transpose(a, axes=None): 

7156 """ 

7157 Permute the dimensions of an array. 

7158 

7159 This function is exactly equivalent to `numpy.transpose`. 

7160 

7161 See Also 

7162 -------- 

7163 numpy.transpose : Equivalent function in top-level NumPy module. 

7164 

7165 Examples 

7166 -------- 

7167 >>> import numpy.ma as ma 

7168 >>> x = ma.arange(4).reshape((2,2)) 

7169 >>> x[1, 1] = ma.masked 

7170 >>> x 

7171 masked_array( 

7172 data=[[0, 1], 

7173 [2, --]], 

7174 mask=[[False, False], 

7175 [False, True]], 

7176 fill_value=999999) 

7177 

7178 >>> ma.transpose(x) 

7179 masked_array( 

7180 data=[[0, 2], 

7181 [1, --]], 

7182 mask=[[False, False], 

7183 [False, True]], 

7184 fill_value=999999) 

7185 """ 

7186 # We can't use 'frommethod', as 'transpose' doesn't take keywords 

7187 try: 

7188 return a.transpose(axes) 

7189 except AttributeError: 

7190 return narray(a, copy=False).transpose(axes).view(MaskedArray) 

7191 

7192 

7193def reshape(a, new_shape, order='C'): 

7194 """ 

7195 Returns an array containing the same data with a new shape. 

7196 

7197 Refer to `MaskedArray.reshape` for full documentation. 

7198 

7199 See Also 

7200 -------- 

7201 MaskedArray.reshape : equivalent function 

7202 

7203 """ 

7204 # We can't use 'frommethod', it whine about some parameters. Dmmit. 

7205 try: 

7206 return a.reshape(new_shape, order=order) 

7207 except AttributeError: 

7208 _tmp = narray(a, copy=False).reshape(new_shape, order=order) 

7209 return _tmp.view(MaskedArray) 

7210 

7211 

7212def resize(x, new_shape): 

7213 """ 

7214 Return a new masked array with the specified size and shape. 

7215 

7216 This is the masked equivalent of the `numpy.resize` function. The new 

7217 array is filled with repeated copies of `x` (in the order that the 

7218 data are stored in memory). If `x` is masked, the new array will be 

7219 masked, and the new mask will be a repetition of the old one. 

7220 

7221 See Also 

7222 -------- 

7223 numpy.resize : Equivalent function in the top level NumPy module. 

7224 

7225 Examples 

7226 -------- 

7227 >>> import numpy.ma as ma 

7228 >>> a = ma.array([[1, 2] ,[3, 4]]) 

7229 >>> a[0, 1] = ma.masked 

7230 >>> a 

7231 masked_array( 

7232 data=[[1, --], 

7233 [3, 4]], 

7234 mask=[[False, True], 

7235 [False, False]], 

7236 fill_value=999999) 

7237 >>> np.resize(a, (3, 3)) 

7238 masked_array( 

7239 data=[[1, 2, 3], 

7240 [4, 1, 2], 

7241 [3, 4, 1]], 

7242 mask=False, 

7243 fill_value=999999) 

7244 >>> ma.resize(a, (3, 3)) 

7245 masked_array( 

7246 data=[[1, --, 3], 

7247 [4, 1, --], 

7248 [3, 4, 1]], 

7249 mask=[[False, True, False], 

7250 [False, False, True], 

7251 [False, False, False]], 

7252 fill_value=999999) 

7253 

7254 A MaskedArray is always returned, regardless of the input type. 

7255 

7256 >>> a = np.array([[1, 2] ,[3, 4]]) 

7257 >>> ma.resize(a, (3, 3)) 

7258 masked_array( 

7259 data=[[1, 2, 3], 

7260 [4, 1, 2], 

7261 [3, 4, 1]], 

7262 mask=False, 

7263 fill_value=999999) 

7264 

7265 """ 

7266 # We can't use _frommethods here, as N.resize is notoriously whiny. 

7267 m = getmask(x) 

7268 if m is not nomask: 

7269 m = np.resize(m, new_shape) 

7270 result = np.resize(x, new_shape).view(get_masked_subclass(x)) 

7271 if result.ndim: 

7272 result._mask = m 

7273 return result 

7274 

7275 

7276def ndim(obj): 

7277 """ 

7278 maskedarray version of the numpy function. 

7279 

7280 """ 

7281 return np.ndim(getdata(obj)) 

7282 

7283ndim.__doc__ = np.ndim.__doc__ 

7284 

7285 

7286def shape(obj): 

7287 "maskedarray version of the numpy function." 

7288 return np.shape(getdata(obj)) 

7289shape.__doc__ = np.shape.__doc__ 

7290 

7291 

7292def size(obj, axis=None): 

7293 "maskedarray version of the numpy function." 

7294 return np.size(getdata(obj), axis) 

7295size.__doc__ = np.size.__doc__ 

7296 

7297 

7298############################################################################## 

7299# Extra functions # 

7300############################################################################## 

7301 

7302 

7303def where(condition, x=_NoValue, y=_NoValue): 

7304 """ 

7305 Return a masked array with elements from `x` or `y`, depending on condition. 

7306 

7307 .. note:: 

7308 When only `condition` is provided, this function is identical to 

7309 `nonzero`. The rest of this documentation covers only the case where 

7310 all three arguments are provided. 

7311 

7312 Parameters 

7313 ---------- 

7314 condition : array_like, bool 

7315 Where True, yield `x`, otherwise yield `y`. 

7316 x, y : array_like, optional 

7317 Values from which to choose. `x`, `y` and `condition` need to be 

7318 broadcastable to some shape. 

7319 

7320 Returns 

7321 ------- 

7322 out : MaskedArray 

7323 An masked array with `masked` elements where the condition is masked, 

7324 elements from `x` where `condition` is True, and elements from `y` 

7325 elsewhere. 

7326 

7327 See Also 

7328 -------- 

7329 numpy.where : Equivalent function in the top-level NumPy module. 

7330 nonzero : The function that is called when x and y are omitted 

7331 

7332 Examples 

7333 -------- 

7334 >>> x = np.ma.array(np.arange(9.).reshape(3, 3), mask=[[0, 1, 0], 

7335 ... [1, 0, 1], 

7336 ... [0, 1, 0]]) 

7337 >>> x 

7338 masked_array( 

7339 data=[[0.0, --, 2.0], 

7340 [--, 4.0, --], 

7341 [6.0, --, 8.0]], 

7342 mask=[[False, True, False], 

7343 [ True, False, True], 

7344 [False, True, False]], 

7345 fill_value=1e+20) 

7346 >>> np.ma.where(x > 5, x, -3.1416) 

7347 masked_array( 

7348 data=[[-3.1416, --, -3.1416], 

7349 [--, -3.1416, --], 

7350 [6.0, --, 8.0]], 

7351 mask=[[False, True, False], 

7352 [ True, False, True], 

7353 [False, True, False]], 

7354 fill_value=1e+20) 

7355 

7356 """ 

7357 

7358 # handle the single-argument case 

7359 missing = (x is _NoValue, y is _NoValue).count(True) 

7360 if missing == 1: 

7361 raise ValueError("Must provide both 'x' and 'y' or neither.") 

7362 if missing == 2: 

7363 return nonzero(condition) 

7364 

7365 # we only care if the condition is true - false or masked pick y 

7366 cf = filled(condition, False) 

7367 xd = getdata(x) 

7368 yd = getdata(y) 

7369 

7370 # we need the full arrays here for correct final dimensions 

7371 cm = getmaskarray(condition) 

7372 xm = getmaskarray(x) 

7373 ym = getmaskarray(y) 

7374 

7375 # deal with the fact that masked.dtype == float64, but we don't actually 

7376 # want to treat it as that. 

7377 if x is masked and y is not masked: 

7378 xd = np.zeros((), dtype=yd.dtype) 

7379 xm = np.ones((), dtype=ym.dtype) 

7380 elif y is masked and x is not masked: 

7381 yd = np.zeros((), dtype=xd.dtype) 

7382 ym = np.ones((), dtype=xm.dtype) 

7383 

7384 data = np.where(cf, xd, yd) 

7385 mask = np.where(cf, xm, ym) 

7386 mask = np.where(cm, np.ones((), dtype=mask.dtype), mask) 

7387 

7388 # collapse the mask, for backwards compatibility 

7389 mask = _shrink_mask(mask) 

7390 

7391 return masked_array(data, mask=mask) 

7392 

7393 

7394def choose(indices, choices, out=None, mode='raise'): 

7395 """ 

7396 Use an index array to construct a new array from a list of choices. 

7397 

7398 Given an array of integers and a list of n choice arrays, this method 

7399 will create a new array that merges each of the choice arrays. Where a 

7400 value in `index` is i, the new array will have the value that choices[i] 

7401 contains in the same place. 

7402 

7403 Parameters 

7404 ---------- 

7405 indices : ndarray of ints 

7406 This array must contain integers in ``[0, n-1]``, where n is the 

7407 number of choices. 

7408 choices : sequence of arrays 

7409 Choice arrays. The index array and all of the choices should be 

7410 broadcastable to the same shape. 

7411 out : array, optional 

7412 If provided, the result will be inserted into this array. It should 

7413 be of the appropriate shape and `dtype`. 

7414 mode : {'raise', 'wrap', 'clip'}, optional 

7415 Specifies how out-of-bounds indices will behave. 

7416 

7417 * 'raise' : raise an error 

7418 * 'wrap' : wrap around 

7419 * 'clip' : clip to the range 

7420 

7421 Returns 

7422 ------- 

7423 merged_array : array 

7424 

7425 See Also 

7426 -------- 

7427 choose : equivalent function 

7428 

7429 Examples 

7430 -------- 

7431 >>> choice = np.array([[1,1,1], [2,2,2], [3,3,3]]) 

7432 >>> a = np.array([2, 1, 0]) 

7433 >>> np.ma.choose(a, choice) 

7434 masked_array(data=[3, 2, 1], 

7435 mask=False, 

7436 fill_value=999999) 

7437 

7438 """ 

7439 def fmask(x): 

7440 "Returns the filled array, or True if masked." 

7441 if x is masked: 

7442 return True 

7443 return filled(x) 

7444 

7445 def nmask(x): 

7446 "Returns the mask, True if ``masked``, False if ``nomask``." 

7447 if x is masked: 

7448 return True 

7449 return getmask(x) 

7450 # Get the indices. 

7451 c = filled(indices, 0) 

7452 # Get the masks. 

7453 masks = [nmask(x) for x in choices] 

7454 data = [fmask(x) for x in choices] 

7455 # Construct the mask 

7456 outputmask = np.choose(c, masks, mode=mode) 

7457 outputmask = make_mask(mask_or(outputmask, getmask(indices)), 

7458 copy=False, shrink=True) 

7459 # Get the choices. 

7460 d = np.choose(c, data, mode=mode, out=out).view(MaskedArray) 

7461 if out is not None: 

7462 if isinstance(out, MaskedArray): 

7463 out.__setmask__(outputmask) 

7464 return out 

7465 d.__setmask__(outputmask) 

7466 return d 

7467 

7468 

7469def round_(a, decimals=0, out=None): 

7470 """ 

7471 Return a copy of a, rounded to 'decimals' places. 

7472 

7473 When 'decimals' is negative, it specifies the number of positions 

7474 to the left of the decimal point. The real and imaginary parts of 

7475 complex numbers are rounded separately. Nothing is done if the 

7476 array is not of float type and 'decimals' is greater than or equal 

7477 to 0. 

7478 

7479 Parameters 

7480 ---------- 

7481 decimals : int 

7482 Number of decimals to round to. May be negative. 

7483 out : array_like 

7484 Existing array to use for output. 

7485 If not given, returns a default copy of a. 

7486 

7487 Notes 

7488 ----- 

7489 If out is given and does not have a mask attribute, the mask of a 

7490 is lost! 

7491 

7492 """ 

7493 if out is None: 

7494 return np.round_(a, decimals, out) 

7495 else: 

7496 np.round_(getdata(a), decimals, out) 

7497 if hasattr(out, '_mask'): 

7498 out._mask = getmask(a) 

7499 return out 

7500round = round_ 

7501 

7502 

7503# Needed by dot, so move here from extras.py. It will still be exported 

7504# from extras.py for compatibility. 

7505def mask_rowcols(a, axis=None): 

7506 """ 

7507 Mask rows and/or columns of a 2D array that contain masked values. 

7508 

7509 Mask whole rows and/or columns of a 2D array that contain 

7510 masked values. The masking behavior is selected using the 

7511 `axis` parameter. 

7512 

7513 - If `axis` is None, rows *and* columns are masked. 

7514 - If `axis` is 0, only rows are masked. 

7515 - If `axis` is 1 or -1, only columns are masked. 

7516 

7517 Parameters 

7518 ---------- 

7519 a : array_like, MaskedArray 

7520 The array to mask. If not a MaskedArray instance (or if no array 

7521 elements are masked). The result is a MaskedArray with `mask` set 

7522 to `nomask` (False). Must be a 2D array. 

7523 axis : int, optional 

7524 Axis along which to perform the operation. If None, applies to a 

7525 flattened version of the array. 

7526 

7527 Returns 

7528 ------- 

7529 a : MaskedArray 

7530 A modified version of the input array, masked depending on the value 

7531 of the `axis` parameter. 

7532 

7533 Raises 

7534 ------ 

7535 NotImplementedError 

7536 If input array `a` is not 2D. 

7537 

7538 See Also 

7539 -------- 

7540 mask_rows : Mask rows of a 2D array that contain masked values. 

7541 mask_cols : Mask cols of a 2D array that contain masked values. 

7542 masked_where : Mask where a condition is met. 

7543 

7544 Notes 

7545 ----- 

7546 The input array's mask is modified by this function. 

7547 

7548 Examples 

7549 -------- 

7550 >>> import numpy.ma as ma 

7551 >>> a = np.zeros((3, 3), dtype=int) 

7552 >>> a[1, 1] = 1 

7553 >>> a 

7554 array([[0, 0, 0], 

7555 [0, 1, 0], 

7556 [0, 0, 0]]) 

7557 >>> a = ma.masked_equal(a, 1) 

7558 >>> a 

7559 masked_array( 

7560 data=[[0, 0, 0], 

7561 [0, --, 0], 

7562 [0, 0, 0]], 

7563 mask=[[False, False, False], 

7564 [False, True, False], 

7565 [False, False, False]], 

7566 fill_value=1) 

7567 >>> ma.mask_rowcols(a) 

7568 masked_array( 

7569 data=[[0, --, 0], 

7570 [--, --, --], 

7571 [0, --, 0]], 

7572 mask=[[False, True, False], 

7573 [ True, True, True], 

7574 [False, True, False]], 

7575 fill_value=1) 

7576 

7577 """ 

7578 a = array(a, subok=False) 

7579 if a.ndim != 2: 

7580 raise NotImplementedError("mask_rowcols works for 2D arrays only.") 

7581 m = getmask(a) 

7582 # Nothing is masked: return a 

7583 if m is nomask or not m.any(): 

7584 return a 

7585 maskedval = m.nonzero() 

7586 a._mask = a._mask.copy() 

7587 if not axis: 

7588 a[np.unique(maskedval[0])] = masked 

7589 if axis in [None, 1, -1]: 

7590 a[:, np.unique(maskedval[1])] = masked 

7591 return a 

7592 

7593 

7594# Include masked dot here to avoid import problems in getting it from 

7595# extras.py. Note that it is not included in __all__, but rather exported 

7596# from extras in order to avoid backward compatibility problems. 

7597def dot(a, b, strict=False, out=None): 

7598 """ 

7599 Return the dot product of two arrays. 

7600 

7601 This function is the equivalent of `numpy.dot` that takes masked values 

7602 into account. Note that `strict` and `out` are in different position 

7603 than in the method version. In order to maintain compatibility with the 

7604 corresponding method, it is recommended that the optional arguments be 

7605 treated as keyword only. At some point that may be mandatory. 

7606 

7607 .. note:: 

7608 Works only with 2-D arrays at the moment. 

7609 

7610 

7611 Parameters 

7612 ---------- 

7613 a, b : masked_array_like 

7614 Inputs arrays. 

7615 strict : bool, optional 

7616 Whether masked data are propagated (True) or set to 0 (False) for 

7617 the computation. Default is False. Propagating the mask means that 

7618 if a masked value appears in a row or column, the whole row or 

7619 column is considered masked. 

7620 out : masked_array, optional 

7621 Output argument. This must have the exact kind that would be returned 

7622 if it was not used. In particular, it must have the right type, must be 

7623 C-contiguous, and its dtype must be the dtype that would be returned 

7624 for `dot(a,b)`. This is a performance feature. Therefore, if these 

7625 conditions are not met, an exception is raised, instead of attempting 

7626 to be flexible. 

7627 

7628 .. versionadded:: 1.10.2 

7629 

7630 See Also 

7631 -------- 

7632 numpy.dot : Equivalent function for ndarrays. 

7633 

7634 Examples 

7635 -------- 

7636 >>> a = np.ma.array([[1, 2, 3], [4, 5, 6]], mask=[[1, 0, 0], [0, 0, 0]]) 

7637 >>> b = np.ma.array([[1, 2], [3, 4], [5, 6]], mask=[[1, 0], [0, 0], [0, 0]]) 

7638 >>> np.ma.dot(a, b) 

7639 masked_array( 

7640 data=[[21, 26], 

7641 [45, 64]], 

7642 mask=[[False, False], 

7643 [False, False]], 

7644 fill_value=999999) 

7645 >>> np.ma.dot(a, b, strict=True) 

7646 masked_array( 

7647 data=[[--, --], 

7648 [--, 64]], 

7649 mask=[[ True, True], 

7650 [ True, False]], 

7651 fill_value=999999) 

7652 

7653 """ 

7654 # !!!: Works only with 2D arrays. There should be a way to get it to run 

7655 # with higher dimension 

7656 if strict and (a.ndim == 2) and (b.ndim == 2): 

7657 a = mask_rowcols(a, 0) 

7658 b = mask_rowcols(b, 1) 

7659 am = ~getmaskarray(a) 

7660 bm = ~getmaskarray(b) 

7661 

7662 if out is None: 

7663 d = np.dot(filled(a, 0), filled(b, 0)) 

7664 m = ~np.dot(am, bm) 

7665 if d.ndim == 0: 

7666 d = np.asarray(d) 

7667 r = d.view(get_masked_subclass(a, b)) 

7668 r.__setmask__(m) 

7669 return r 

7670 else: 

7671 d = np.dot(filled(a, 0), filled(b, 0), out._data) 

7672 if out.mask.shape != d.shape: 

7673 out._mask = np.empty(d.shape, MaskType) 

7674 np.dot(am, bm, out._mask) 

7675 np.logical_not(out._mask, out._mask) 

7676 return out 

7677 

7678 

7679def inner(a, b): 

7680 """ 

7681 Returns the inner product of a and b for arrays of floating point types. 

7682 

7683 Like the generic NumPy equivalent the product sum is over the last dimension 

7684 of a and b. The first argument is not conjugated. 

7685 

7686 """ 

7687 fa = filled(a, 0) 

7688 fb = filled(b, 0) 

7689 if fa.ndim == 0: 

7690 fa.shape = (1,) 

7691 if fb.ndim == 0: 

7692 fb.shape = (1,) 

7693 return np.inner(fa, fb).view(MaskedArray) 

7694inner.__doc__ = doc_note(np.inner.__doc__, 

7695 "Masked values are replaced by 0.") 

7696innerproduct = inner 

7697 

7698 

7699def outer(a, b): 

7700 "maskedarray version of the numpy function." 

7701 fa = filled(a, 0).ravel() 

7702 fb = filled(b, 0).ravel() 

7703 d = np.outer(fa, fb) 

7704 ma = getmask(a) 

7705 mb = getmask(b) 

7706 if ma is nomask and mb is nomask: 

7707 return masked_array(d) 

7708 ma = getmaskarray(a) 

7709 mb = getmaskarray(b) 

7710 m = make_mask(1 - np.outer(1 - ma, 1 - mb), copy=False) 

7711 return masked_array(d, mask=m) 

7712outer.__doc__ = doc_note(np.outer.__doc__, 

7713 "Masked values are replaced by 0.") 

7714outerproduct = outer 

7715 

7716 

7717def _convolve_or_correlate(f, a, v, mode, propagate_mask): 

7718 """ 

7719 Helper function for ma.correlate and ma.convolve 

7720 """ 

7721 if propagate_mask: 

7722 # results which are contributed to by either item in any pair being invalid 

7723 mask = ( 

7724 f(getmaskarray(a), np.ones(np.shape(v), dtype=bool), mode=mode) 

7725 | f(np.ones(np.shape(a), dtype=bool), getmaskarray(v), mode=mode) 

7726 ) 

7727 data = f(getdata(a), getdata(v), mode=mode) 

7728 else: 

7729 # results which are not contributed to by any pair of valid elements 

7730 mask = ~f(~getmaskarray(a), ~getmaskarray(v)) 

7731 data = f(filled(a, 0), filled(v, 0), mode=mode) 

7732 

7733 return masked_array(data, mask=mask) 

7734 

7735 

7736def correlate(a, v, mode='valid', propagate_mask=True): 

7737 """ 

7738 Cross-correlation of two 1-dimensional sequences. 

7739 

7740 Parameters 

7741 ---------- 

7742 a, v : array_like 

7743 Input sequences. 

7744 mode : {'valid', 'same', 'full'}, optional 

7745 Refer to the `np.convolve` docstring. Note that the default 

7746 is 'valid', unlike `convolve`, which uses 'full'. 

7747 propagate_mask : bool 

7748 If True, then a result element is masked if any masked element contributes towards it. 

7749 If False, then a result element is only masked if no non-masked element 

7750 contribute towards it 

7751 

7752 Returns 

7753 ------- 

7754 out : MaskedArray 

7755 Discrete cross-correlation of `a` and `v`. 

7756 

7757 See Also 

7758 -------- 

7759 numpy.correlate : Equivalent function in the top-level NumPy module. 

7760 """ 

7761 return _convolve_or_correlate(np.correlate, a, v, mode, propagate_mask) 

7762 

7763 

7764def convolve(a, v, mode='full', propagate_mask=True): 

7765 """ 

7766 Returns the discrete, linear convolution of two one-dimensional sequences. 

7767 

7768 Parameters 

7769 ---------- 

7770 a, v : array_like 

7771 Input sequences. 

7772 mode : {'valid', 'same', 'full'}, optional 

7773 Refer to the `np.convolve` docstring. 

7774 propagate_mask : bool 

7775 If True, then if any masked element is included in the sum for a result 

7776 element, then the result is masked. 

7777 If False, then the result element is only masked if no non-masked cells 

7778 contribute towards it 

7779 

7780 Returns 

7781 ------- 

7782 out : MaskedArray 

7783 Discrete, linear convolution of `a` and `v`. 

7784 

7785 See Also 

7786 -------- 

7787 numpy.convolve : Equivalent function in the top-level NumPy module. 

7788 """ 

7789 return _convolve_or_correlate(np.convolve, a, v, mode, propagate_mask) 

7790 

7791 

7792def allequal(a, b, fill_value=True): 

7793 """ 

7794 Return True if all entries of a and b are equal, using 

7795 fill_value as a truth value where either or both are masked. 

7796 

7797 Parameters 

7798 ---------- 

7799 a, b : array_like 

7800 Input arrays to compare. 

7801 fill_value : bool, optional 

7802 Whether masked values in a or b are considered equal (True) or not 

7803 (False). 

7804 

7805 Returns 

7806 ------- 

7807 y : bool 

7808 Returns True if the two arrays are equal within the given 

7809 tolerance, False otherwise. If either array contains NaN, 

7810 then False is returned. 

7811 

7812 See Also 

7813 -------- 

7814 all, any 

7815 numpy.ma.allclose 

7816 

7817 Examples 

7818 -------- 

7819 >>> a = np.ma.array([1e10, 1e-7, 42.0], mask=[0, 0, 1]) 

7820 >>> a 

7821 masked_array(data=[10000000000.0, 1e-07, --], 

7822 mask=[False, False, True], 

7823 fill_value=1e+20) 

7824 

7825 >>> b = np.array([1e10, 1e-7, -42.0]) 

7826 >>> b 

7827 array([ 1.00000000e+10, 1.00000000e-07, -4.20000000e+01]) 

7828 >>> np.ma.allequal(a, b, fill_value=False) 

7829 False 

7830 >>> np.ma.allequal(a, b) 

7831 True 

7832 

7833 """ 

7834 m = mask_or(getmask(a), getmask(b)) 

7835 if m is nomask: 

7836 x = getdata(a) 

7837 y = getdata(b) 

7838 d = umath.equal(x, y) 

7839 return d.all() 

7840 elif fill_value: 

7841 x = getdata(a) 

7842 y = getdata(b) 

7843 d = umath.equal(x, y) 

7844 dm = array(d, mask=m, copy=False) 

7845 return dm.filled(True).all(None) 

7846 else: 

7847 return False 

7848 

7849 

7850def allclose(a, b, masked_equal=True, rtol=1e-5, atol=1e-8): 

7851 """ 

7852 Returns True if two arrays are element-wise equal within a tolerance. 

7853 

7854 This function is equivalent to `allclose` except that masked values 

7855 are treated as equal (default) or unequal, depending on the `masked_equal` 

7856 argument. 

7857 

7858 Parameters 

7859 ---------- 

7860 a, b : array_like 

7861 Input arrays to compare. 

7862 masked_equal : bool, optional 

7863 Whether masked values in `a` and `b` are considered equal (True) or not 

7864 (False). They are considered equal by default. 

7865 rtol : float, optional 

7866 Relative tolerance. The relative difference is equal to ``rtol * b``. 

7867 Default is 1e-5. 

7868 atol : float, optional 

7869 Absolute tolerance. The absolute difference is equal to `atol`. 

7870 Default is 1e-8. 

7871 

7872 Returns 

7873 ------- 

7874 y : bool 

7875 Returns True if the two arrays are equal within the given 

7876 tolerance, False otherwise. If either array contains NaN, then 

7877 False is returned. 

7878 

7879 See Also 

7880 -------- 

7881 all, any 

7882 numpy.allclose : the non-masked `allclose`. 

7883 

7884 Notes 

7885 ----- 

7886 If the following equation is element-wise True, then `allclose` returns 

7887 True:: 

7888 

7889 absolute(`a` - `b`) <= (`atol` + `rtol` * absolute(`b`)) 

7890 

7891 Return True if all elements of `a` and `b` are equal subject to 

7892 given tolerances. 

7893 

7894 Examples 

7895 -------- 

7896 >>> a = np.ma.array([1e10, 1e-7, 42.0], mask=[0, 0, 1]) 

7897 >>> a 

7898 masked_array(data=[10000000000.0, 1e-07, --], 

7899 mask=[False, False, True], 

7900 fill_value=1e+20) 

7901 >>> b = np.ma.array([1e10, 1e-8, -42.0], mask=[0, 0, 1]) 

7902 >>> np.ma.allclose(a, b) 

7903 False 

7904 

7905 >>> a = np.ma.array([1e10, 1e-8, 42.0], mask=[0, 0, 1]) 

7906 >>> b = np.ma.array([1.00001e10, 1e-9, -42.0], mask=[0, 0, 1]) 

7907 >>> np.ma.allclose(a, b) 

7908 True 

7909 >>> np.ma.allclose(a, b, masked_equal=False) 

7910 False 

7911 

7912 Masked values are not compared directly. 

7913 

7914 >>> a = np.ma.array([1e10, 1e-8, 42.0], mask=[0, 0, 1]) 

7915 >>> b = np.ma.array([1.00001e10, 1e-9, 42.0], mask=[0, 0, 1]) 

7916 >>> np.ma.allclose(a, b) 

7917 True 

7918 >>> np.ma.allclose(a, b, masked_equal=False) 

7919 False 

7920 

7921 """ 

7922 x = masked_array(a, copy=False) 

7923 y = masked_array(b, copy=False) 

7924 

7925 # make sure y is an inexact type to avoid abs(MIN_INT); will cause 

7926 # casting of x later. 

7927 # NOTE: We explicitly allow timedelta, which used to work. This could 

7928 # possibly be deprecated. See also gh-18286. 

7929 # timedelta works if `atol` is an integer or also a timedelta. 

7930 # Although, the default tolerances are unlikely to be useful 

7931 if y.dtype.kind != "m": 

7932 dtype = np.result_type(y, 1.) 

7933 if y.dtype != dtype: 

7934 y = masked_array(y, dtype=dtype, copy=False) 

7935 

7936 m = mask_or(getmask(x), getmask(y)) 

7937 xinf = np.isinf(masked_array(x, copy=False, mask=m)).filled(False) 

7938 # If we have some infs, they should fall at the same place. 

7939 if not np.all(xinf == filled(np.isinf(y), False)): 

7940 return False 

7941 # No infs at all 

7942 if not np.any(xinf): 

7943 d = filled(less_equal(absolute(x - y), atol + rtol * absolute(y)), 

7944 masked_equal) 

7945 return np.all(d) 

7946 

7947 if not np.all(filled(x[xinf] == y[xinf], masked_equal)): 

7948 return False 

7949 x = x[~xinf] 

7950 y = y[~xinf] 

7951 

7952 d = filled(less_equal(absolute(x - y), atol + rtol * absolute(y)), 

7953 masked_equal) 

7954 

7955 return np.all(d) 

7956 

7957 

7958def asarray(a, dtype=None, order=None): 

7959 """ 

7960 Convert the input to a masked array of the given data-type. 

7961 

7962 No copy is performed if the input is already an `ndarray`. If `a` is 

7963 a subclass of `MaskedArray`, a base class `MaskedArray` is returned. 

7964 

7965 Parameters 

7966 ---------- 

7967 a : array_like 

7968 Input data, in any form that can be converted to a masked array. This 

7969 includes lists, lists of tuples, tuples, tuples of tuples, tuples 

7970 of lists, ndarrays and masked arrays. 

7971 dtype : dtype, optional 

7972 By default, the data-type is inferred from the input data. 

7973 order : {'C', 'F'}, optional 

7974 Whether to use row-major ('C') or column-major ('FORTRAN') memory 

7975 representation. Default is 'C'. 

7976 

7977 Returns 

7978 ------- 

7979 out : MaskedArray 

7980 Masked array interpretation of `a`. 

7981 

7982 See Also 

7983 -------- 

7984 asanyarray : Similar to `asarray`, but conserves subclasses. 

7985 

7986 Examples 

7987 -------- 

7988 >>> x = np.arange(10.).reshape(2, 5) 

7989 >>> x 

7990 array([[0., 1., 2., 3., 4.], 

7991 [5., 6., 7., 8., 9.]]) 

7992 >>> np.ma.asarray(x) 

7993 masked_array( 

7994 data=[[0., 1., 2., 3., 4.], 

7995 [5., 6., 7., 8., 9.]], 

7996 mask=False, 

7997 fill_value=1e+20) 

7998 >>> type(np.ma.asarray(x)) 

7999 <class 'numpy.ma.core.MaskedArray'> 

8000 

8001 """ 

8002 order = order or 'C' 

8003 return masked_array(a, dtype=dtype, copy=False, keep_mask=True, 

8004 subok=False, order=order) 

8005 

8006 

8007def asanyarray(a, dtype=None): 

8008 """ 

8009 Convert the input to a masked array, conserving subclasses. 

8010 

8011 If `a` is a subclass of `MaskedArray`, its class is conserved. 

8012 No copy is performed if the input is already an `ndarray`. 

8013 

8014 Parameters 

8015 ---------- 

8016 a : array_like 

8017 Input data, in any form that can be converted to an array. 

8018 dtype : dtype, optional 

8019 By default, the data-type is inferred from the input data. 

8020 order : {'C', 'F'}, optional 

8021 Whether to use row-major ('C') or column-major ('FORTRAN') memory 

8022 representation. Default is 'C'. 

8023 

8024 Returns 

8025 ------- 

8026 out : MaskedArray 

8027 MaskedArray interpretation of `a`. 

8028 

8029 See Also 

8030 -------- 

8031 asarray : Similar to `asanyarray`, but does not conserve subclass. 

8032 

8033 Examples 

8034 -------- 

8035 >>> x = np.arange(10.).reshape(2, 5) 

8036 >>> x 

8037 array([[0., 1., 2., 3., 4.], 

8038 [5., 6., 7., 8., 9.]]) 

8039 >>> np.ma.asanyarray(x) 

8040 masked_array( 

8041 data=[[0., 1., 2., 3., 4.], 

8042 [5., 6., 7., 8., 9.]], 

8043 mask=False, 

8044 fill_value=1e+20) 

8045 >>> type(np.ma.asanyarray(x)) 

8046 <class 'numpy.ma.core.MaskedArray'> 

8047 

8048 """ 

8049 # workaround for #8666, to preserve identity. Ideally the bottom line 

8050 # would handle this for us. 

8051 if isinstance(a, MaskedArray) and (dtype is None or dtype == a.dtype): 

8052 return a 

8053 return masked_array(a, dtype=dtype, copy=False, keep_mask=True, subok=True) 

8054 

8055 

8056############################################################################## 

8057# Pickling # 

8058############################################################################## 

8059 

8060def _pickle_warn(method): 

8061 # NumPy 1.15.0, 2017-12-10 

8062 warnings.warn( 

8063 f"np.ma.{method} is deprecated, use pickle.{method} instead", 

8064 DeprecationWarning, stacklevel=3) 

8065 

8066 

8067def fromfile(file, dtype=float, count=-1, sep=''): 

8068 raise NotImplementedError( 

8069 "fromfile() not yet implemented for a MaskedArray.") 

8070 

8071 

8072def fromflex(fxarray): 

8073 """ 

8074 Build a masked array from a suitable flexible-type array. 

8075 

8076 The input array has to have a data-type with ``_data`` and ``_mask`` 

8077 fields. This type of array is output by `MaskedArray.toflex`. 

8078 

8079 Parameters 

8080 ---------- 

8081 fxarray : ndarray 

8082 The structured input array, containing ``_data`` and ``_mask`` 

8083 fields. If present, other fields are discarded. 

8084 

8085 Returns 

8086 ------- 

8087 result : MaskedArray 

8088 The constructed masked array. 

8089 

8090 See Also 

8091 -------- 

8092 MaskedArray.toflex : Build a flexible-type array from a masked array. 

8093 

8094 Examples 

8095 -------- 

8096 >>> x = np.ma.array(np.arange(9).reshape(3, 3), mask=[0] + [1, 0] * 4) 

8097 >>> rec = x.toflex() 

8098 >>> rec 

8099 array([[(0, False), (1, True), (2, False)], 

8100 [(3, True), (4, False), (5, True)], 

8101 [(6, False), (7, True), (8, False)]], 

8102 dtype=[('_data', '<i8'), ('_mask', '?')]) 

8103 >>> x2 = np.ma.fromflex(rec) 

8104 >>> x2 

8105 masked_array( 

8106 data=[[0, --, 2], 

8107 [--, 4, --], 

8108 [6, --, 8]], 

8109 mask=[[False, True, False], 

8110 [ True, False, True], 

8111 [False, True, False]], 

8112 fill_value=999999) 

8113 

8114 Extra fields can be present in the structured array but are discarded: 

8115 

8116 >>> dt = [('_data', '<i4'), ('_mask', '|b1'), ('field3', '<f4')] 

8117 >>> rec2 = np.zeros((2, 2), dtype=dt) 

8118 >>> rec2 

8119 array([[(0, False, 0.), (0, False, 0.)], 

8120 [(0, False, 0.), (0, False, 0.)]], 

8121 dtype=[('_data', '<i4'), ('_mask', '?'), ('field3', '<f4')]) 

8122 >>> y = np.ma.fromflex(rec2) 

8123 >>> y 

8124 masked_array( 

8125 data=[[0, 0], 

8126 [0, 0]], 

8127 mask=[[False, False], 

8128 [False, False]], 

8129 fill_value=999999, 

8130 dtype=int32) 

8131 

8132 """ 

8133 return masked_array(fxarray['_data'], mask=fxarray['_mask']) 

8134 

8135 

8136class _convert2ma: 

8137 

8138 """ 

8139 Convert functions from numpy to numpy.ma. 

8140 

8141 Parameters 

8142 ---------- 

8143 _methodname : string 

8144 Name of the method to transform. 

8145 

8146 """ 

8147 __doc__ = None 

8148 

8149 def __init__(self, funcname, np_ret, np_ma_ret, params=None): 

8150 self._func = getattr(np, funcname) 

8151 self.__doc__ = self.getdoc(np_ret, np_ma_ret) 

8152 self._extras = params or {} 

8153 

8154 def getdoc(self, np_ret, np_ma_ret): 

8155 "Return the doc of the function (from the doc of the method)." 

8156 doc = getattr(self._func, '__doc__', None) 

8157 sig = get_object_signature(self._func) 

8158 if doc: 8158 ↛ 8164line 8158 didn't jump to line 8164, because the condition on line 8158 was never false

8159 doc = self._replace_return_type(doc, np_ret, np_ma_ret) 

8160 # Add the signature of the function at the beginning of the doc 

8161 if sig: 

8162 sig = "%s%s\n" % (self._func.__name__, sig) 

8163 doc = sig + doc 

8164 return doc 

8165 

8166 def _replace_return_type(self, doc, np_ret, np_ma_ret): 

8167 """ 

8168 Replace documentation of ``np`` function's return type. 

8169 

8170 Replaces it with the proper type for the ``np.ma`` function. 

8171 

8172 Parameters 

8173 ---------- 

8174 doc : str 

8175 The documentation of the ``np`` method. 

8176 np_ret : str 

8177 The return type string of the ``np`` method that we want to 

8178 replace. (e.g. "out : ndarray") 

8179 np_ma_ret : str 

8180 The return type string of the ``np.ma`` method. 

8181 (e.g. "out : MaskedArray") 

8182 """ 

8183 if np_ret not in doc: 8183 ↛ 8184line 8183 didn't jump to line 8184, because the condition on line 8183 was never true

8184 raise RuntimeError( 

8185 f"Failed to replace `{np_ret}` with `{np_ma_ret}`. " 

8186 f"The documentation string for return type, {np_ret}, is not " 

8187 f"found in the docstring for `np.{self._func.__name__}`. " 

8188 f"Fix the docstring for `np.{self._func.__name__}` or " 

8189 "update the expected string for return type." 

8190 ) 

8191 

8192 return doc.replace(np_ret, np_ma_ret) 

8193 

8194 def __call__(self, *args, **params): 

8195 # Find the common parameters to the call and the definition 

8196 _extras = self._extras 

8197 common_params = set(params).intersection(_extras) 

8198 # Drop the common parameters from the call 

8199 for p in common_params: 

8200 _extras[p] = params.pop(p) 

8201 # Get the result 

8202 result = self._func.__call__(*args, **params).view(MaskedArray) 

8203 if "fill_value" in common_params: 

8204 result.fill_value = _extras.get("fill_value", None) 

8205 if "hardmask" in common_params: 

8206 result._hardmask = bool(_extras.get("hard_mask", False)) 

8207 return result 

8208 

8209 

8210arange = _convert2ma( 

8211 'arange', 

8212 params=dict(fill_value=None, hardmask=False), 

8213 np_ret='arange : ndarray', 

8214 np_ma_ret='arange : MaskedArray', 

8215) 

8216clip = _convert2ma( 

8217 'clip', 

8218 params=dict(fill_value=None, hardmask=False), 

8219 np_ret='clipped_array : ndarray', 

8220 np_ma_ret='clipped_array : MaskedArray', 

8221) 

8222diff = _convert2ma( 

8223 'diff', 

8224 params=dict(fill_value=None, hardmask=False), 

8225 np_ret='diff : ndarray', 

8226 np_ma_ret='diff : MaskedArray', 

8227) 

8228empty = _convert2ma( 

8229 'empty', 

8230 params=dict(fill_value=None, hardmask=False), 

8231 np_ret='out : ndarray', 

8232 np_ma_ret='out : MaskedArray', 

8233) 

8234empty_like = _convert2ma( 

8235 'empty_like', 

8236 np_ret='out : ndarray', 

8237 np_ma_ret='out : MaskedArray', 

8238) 

8239frombuffer = _convert2ma( 

8240 'frombuffer', 

8241 np_ret='out : ndarray', 

8242 np_ma_ret='out: MaskedArray', 

8243) 

8244fromfunction = _convert2ma( 

8245 'fromfunction', 

8246 np_ret='fromfunction : any', 

8247 np_ma_ret='fromfunction: MaskedArray', 

8248) 

8249identity = _convert2ma( 

8250 'identity', 

8251 params=dict(fill_value=None, hardmask=False), 

8252 np_ret='out : ndarray', 

8253 np_ma_ret='out : MaskedArray', 

8254) 

8255indices = _convert2ma( 

8256 'indices', 

8257 params=dict(fill_value=None, hardmask=False), 

8258 np_ret='grid : one ndarray or tuple of ndarrays', 

8259 np_ma_ret='grid : one MaskedArray or tuple of MaskedArrays', 

8260) 

8261ones = _convert2ma( 

8262 'ones', 

8263 params=dict(fill_value=None, hardmask=False), 

8264 np_ret='out : ndarray', 

8265 np_ma_ret='out : MaskedArray', 

8266) 

8267ones_like = _convert2ma( 

8268 'ones_like', 

8269 np_ret='out : ndarray', 

8270 np_ma_ret='out : MaskedArray', 

8271) 

8272squeeze = _convert2ma( 

8273 'squeeze', 

8274 params=dict(fill_value=None, hardmask=False), 

8275 np_ret='squeezed : ndarray', 

8276 np_ma_ret='squeezed : MaskedArray', 

8277) 

8278zeros = _convert2ma( 

8279 'zeros', 

8280 params=dict(fill_value=None, hardmask=False), 

8281 np_ret='out : ndarray', 

8282 np_ma_ret='out : MaskedArray', 

8283) 

8284zeros_like = _convert2ma( 

8285 'zeros_like', 

8286 np_ret='out : ndarray', 

8287 np_ma_ret='out : MaskedArray', 

8288) 

8289 

8290 

8291def append(a, b, axis=None): 

8292 """Append values to the end of an array. 

8293 

8294 .. versionadded:: 1.9.0 

8295 

8296 Parameters 

8297 ---------- 

8298 a : array_like 

8299 Values are appended to a copy of this array. 

8300 b : array_like 

8301 These values are appended to a copy of `a`. It must be of the 

8302 correct shape (the same shape as `a`, excluding `axis`). If `axis` 

8303 is not specified, `b` can be any shape and will be flattened 

8304 before use. 

8305 axis : int, optional 

8306 The axis along which `v` are appended. If `axis` is not given, 

8307 both `a` and `b` are flattened before use. 

8308 

8309 Returns 

8310 ------- 

8311 append : MaskedArray 

8312 A copy of `a` with `b` appended to `axis`. Note that `append` 

8313 does not occur in-place: a new array is allocated and filled. If 

8314 `axis` is None, the result is a flattened array. 

8315 

8316 See Also 

8317 -------- 

8318 numpy.append : Equivalent function in the top-level NumPy module. 

8319 

8320 Examples 

8321 -------- 

8322 >>> import numpy.ma as ma 

8323 >>> a = ma.masked_values([1, 2, 3], 2) 

8324 >>> b = ma.masked_values([[4, 5, 6], [7, 8, 9]], 7) 

8325 >>> ma.append(a, b) 

8326 masked_array(data=[1, --, 3, 4, 5, 6, --, 8, 9], 

8327 mask=[False, True, False, False, False, False, True, False, 

8328 False], 

8329 fill_value=999999) 

8330 """ 

8331 return concatenate([a, b], axis)