Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/numpy/ma/extras.py: 17%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

535 statements  

1""" 

2Masked arrays add-ons. 

3 

4A collection of utilities for `numpy.ma`. 

5 

6:author: Pierre Gerard-Marchant 

7:contact: pierregm_at_uga_dot_edu 

8 

9""" 

10__all__ = [ 

11 'apply_along_axis', 'apply_over_axes', 'atleast_1d', 'atleast_2d', 

12 'atleast_3d', 'average', 'clump_masked', 'clump_unmasked', 'column_stack', 

13 'compress_cols', 'compress_nd', 'compress_rowcols', 'compress_rows', 

14 'count_masked', 'corrcoef', 'cov', 'diagflat', 'dot', 'dstack', 'ediff1d', 

15 'flatnotmasked_contiguous', 'flatnotmasked_edges', 'hsplit', 'hstack', 

16 'isin', 'in1d', 'intersect1d', 'mask_cols', 'mask_rowcols', 'mask_rows', 

17 'masked_all', 'masked_all_like', 'median', 'mr_', 'ndenumerate', 

18 'notmasked_contiguous', 'notmasked_edges', 'polyfit', 'row_stack', 

19 'setdiff1d', 'setxor1d', 'stack', 'unique', 'union1d', 'vander', 'vstack', 

20 ] 

21 

22import functools 

23import itertools 

24import warnings 

25 

26import numpy as np 

27from numpy import array as nxarray, ndarray 

28from numpy.lib._function_base_impl import _ureduce 

29from numpy.lib._index_tricks_impl import AxisConcatenator 

30from numpy.lib.array_utils import normalize_axis_index, normalize_axis_tuple 

31 

32from . import core as ma 

33from .core import ( # noqa: F401 

34 MAError, 

35 MaskedArray, 

36 add, 

37 array, 

38 asarray, 

39 concatenate, 

40 count, 

41 dot, 

42 filled, 

43 get_masked_subclass, 

44 getdata, 

45 getmask, 

46 getmaskarray, 

47 make_mask_descr, 

48 mask_or, 

49 masked, 

50 masked_array, 

51 nomask, 

52 ones, 

53 sort, 

54 zeros, 

55) 

56 

57 

58def issequence(seq): 

59 """ 

60 Is seq a sequence (ndarray, list or tuple)? 

61 

62 """ 

63 return isinstance(seq, (ndarray, tuple, list)) 

64 

65 

66def count_masked(arr, axis=None): 

67 """ 

68 Count the number of masked elements along the given axis. 

69 

70 Parameters 

71 ---------- 

72 arr : array_like 

73 An array with (possibly) masked elements. 

74 axis : int, optional 

75 Axis along which to count. If None (default), a flattened 

76 version of the array is used. 

77 

78 Returns 

79 ------- 

80 count : int, ndarray 

81 The total number of masked elements (axis=None) or the number 

82 of masked elements along each slice of the given axis. 

83 

84 See Also 

85 -------- 

86 MaskedArray.count : Count non-masked elements. 

87 

88 Examples 

89 -------- 

90 >>> import numpy as np 

91 >>> a = np.arange(9).reshape((3,3)) 

92 >>> a = np.ma.array(a) 

93 >>> a[1, 0] = np.ma.masked 

94 >>> a[1, 2] = np.ma.masked 

95 >>> a[2, 1] = np.ma.masked 

96 >>> a 

97 masked_array( 

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

99 [--, 4, --], 

100 [6, --, 8]], 

101 mask=[[False, False, False], 

102 [ True, False, True], 

103 [False, True, False]], 

104 fill_value=999999) 

105 >>> np.ma.count_masked(a) 

106 3 

107 

108 When the `axis` keyword is used an array is returned. 

109 

110 >>> np.ma.count_masked(a, axis=0) 

111 array([1, 1, 1]) 

112 >>> np.ma.count_masked(a, axis=1) 

113 array([0, 2, 1]) 

114 

115 """ 

116 m = getmaskarray(arr) 

117 return m.sum(axis) 

118 

119 

120def masked_all(shape, dtype=float): 

121 """ 

122 Empty masked array with all elements masked. 

123 

124 Return an empty masked array of the given shape and dtype, where all the 

125 data are masked. 

126 

127 Parameters 

128 ---------- 

129 shape : int or tuple of ints 

130 Shape of the required MaskedArray, e.g., ``(2, 3)`` or ``2``. 

131 dtype : dtype, optional 

132 Data type of the output. 

133 

134 Returns 

135 ------- 

136 a : MaskedArray 

137 A masked array with all data masked. 

138 

139 See Also 

140 -------- 

141 masked_all_like : Empty masked array modelled on an existing array. 

142 

143 Notes 

144 ----- 

145 Unlike other masked array creation functions (e.g. `numpy.ma.zeros`, 

146 `numpy.ma.ones`, `numpy.ma.full`), `masked_all` does not initialize the 

147 values of the array, and may therefore be marginally faster. However, 

148 the values stored in the newly allocated array are arbitrary. For 

149 reproducible behavior, be sure to set each element of the array before 

150 reading. 

151 

152 Examples 

153 -------- 

154 >>> import numpy as np 

155 >>> np.ma.masked_all((3, 3)) 

156 masked_array( 

157 data=[[--, --, --], 

158 [--, --, --], 

159 [--, --, --]], 

160 mask=[[ True, True, True], 

161 [ True, True, True], 

162 [ True, True, True]], 

163 fill_value=1e+20, 

164 dtype=float64) 

165 

166 The `dtype` parameter defines the underlying data type. 

167 

168 >>> a = np.ma.masked_all((3, 3)) 

169 >>> a.dtype 

170 dtype('float64') 

171 >>> a = np.ma.masked_all((3, 3), dtype=np.int32) 

172 >>> a.dtype 

173 dtype('int32') 

174 

175 """ 

176 a = masked_array(np.empty(shape, dtype), 

177 mask=np.ones(shape, make_mask_descr(dtype))) 

178 return a 

179 

180 

181def masked_all_like(arr): 

182 """ 

183 Empty masked array with the properties of an existing array. 

184 

185 Return an empty masked array of the same shape and dtype as 

186 the array `arr`, where all the data are masked. 

187 

188 Parameters 

189 ---------- 

190 arr : ndarray 

191 An array describing the shape and dtype of the required MaskedArray. 

192 

193 Returns 

194 ------- 

195 a : MaskedArray 

196 A masked array with all data masked. 

197 

198 Raises 

199 ------ 

200 AttributeError 

201 If `arr` doesn't have a shape attribute (i.e. not an ndarray) 

202 

203 See Also 

204 -------- 

205 masked_all : Empty masked array with all elements masked. 

206 

207 Notes 

208 ----- 

209 Unlike other masked array creation functions (e.g. `numpy.ma.zeros_like`, 

210 `numpy.ma.ones_like`, `numpy.ma.full_like`), `masked_all_like` does not 

211 initialize the values of the array, and may therefore be marginally 

212 faster. However, the values stored in the newly allocated array are 

213 arbitrary. For reproducible behavior, be sure to set each element of the 

214 array before reading. 

215 

216 Examples 

217 -------- 

218 >>> import numpy as np 

219 >>> arr = np.zeros((2, 3), dtype=np.float32) 

220 >>> arr 

221 array([[0., 0., 0.], 

222 [0., 0., 0.]], dtype=float32) 

223 >>> np.ma.masked_all_like(arr) 

224 masked_array( 

225 data=[[--, --, --], 

226 [--, --, --]], 

227 mask=[[ True, True, True], 

228 [ True, True, True]], 

229 fill_value=np.float64(1e+20), 

230 dtype=float32) 

231 

232 The dtype of the masked array matches the dtype of `arr`. 

233 

234 >>> arr.dtype 

235 dtype('float32') 

236 >>> np.ma.masked_all_like(arr).dtype 

237 dtype('float32') 

238 

239 """ 

240 a = np.empty_like(arr).view(MaskedArray) 

241 a._mask = np.ones(a.shape, dtype=make_mask_descr(a.dtype)) 

242 return a 

243 

244 

245#####-------------------------------------------------------------------------- 

246#---- --- Standard functions --- 

247#####-------------------------------------------------------------------------- 

248 

249def _fromnxfunction_function(_fromnxfunction): 

250 """ 

251 Decorator to wrap a "_fromnxfunction" function, wrapping a numpy function as a 

252 masked array function, with proper docstring and name. 

253 

254 Parameters 

255 ---------- 

256 _fromnxfunction : ({params}) -> ndarray, {params}) -> masked_array 

257 Wrapper function that calls the wrapped numpy function 

258 

259 Returns 

260 ------- 

261 decorator : (f: ({params}) -> ndarray) -> ({params}) -> masked_array 

262 Function that accepts a numpy function and returns a masked array function 

263 

264 """ 

265 def decorator(npfunc, /): 

266 def wrapper(*args, **kwargs): 

267 return _fromnxfunction(npfunc, *args, **kwargs) 

268 

269 functools.update_wrapper(wrapper, npfunc, assigned=("__name__", "__qualname__")) 

270 wrapper.__doc__ = ma.doc_note( 

271 npfunc.__doc__, 

272 "The function is applied to both the ``_data`` and the ``_mask``, if any.", 

273 ) 

274 return wrapper 

275 

276 return decorator 

277 

278 

279@_fromnxfunction_function 

280def _fromnxfunction_single(npfunc, a, /, *args, **kwargs): 

281 """ 

282 Wraps a NumPy function that can be called with a single array argument followed by 

283 auxiliary args that are passed verbatim for both the data and mask calls. 

284 """ 

285 return masked_array( 

286 data=npfunc(np.asarray(a), *args, **kwargs), 

287 mask=npfunc(getmaskarray(a), *args, **kwargs), 

288 ) 

289 

290 

291@_fromnxfunction_function 

292def _fromnxfunction_seq(npfunc, arys, /, *args, **kwargs): 

293 """ 

294 Wraps a NumPy function that can be called with a single sequence of arrays followed 

295 by auxiliary args that are passed verbatim for both the data and mask calls. 

296 """ 

297 return masked_array( 

298 data=npfunc(tuple(np.asarray(a) for a in arys), *args, **kwargs), 

299 mask=npfunc(tuple(getmaskarray(a) for a in arys), *args, **kwargs), 

300 ) 

301 

302@_fromnxfunction_function 

303def _fromnxfunction_allargs(npfunc, /, *arys, **kwargs): 

304 """ 

305 Wraps a NumPy function that can be called with multiple array arguments. 

306 All args are converted to arrays even if they are not so already. 

307 This makes it possible to process scalars as 1-D arrays. 

308 Only keyword arguments are passed through verbatim for the data and mask calls. 

309 Arrays arguments are processed independently and the results are returned in a list. 

310 If only one arg is present, the return value is just the processed array instead of 

311 a list. 

312 """ 

313 out = tuple( 

314 masked_array( 

315 data=npfunc(np.asarray(a), **kwargs), 

316 mask=npfunc(getmaskarray(a), **kwargs), 

317 ) 

318 for a in arys 

319 ) 

320 return out[0] if len(out) == 1 else out 

321 

322 

323atleast_1d = _fromnxfunction_allargs(np.atleast_1d) 

324atleast_2d = _fromnxfunction_allargs(np.atleast_2d) 

325atleast_3d = _fromnxfunction_allargs(np.atleast_3d) 

326 

327vstack = row_stack = _fromnxfunction_seq(np.vstack) 

328hstack = _fromnxfunction_seq(np.hstack) 

329column_stack = _fromnxfunction_seq(np.column_stack) 

330dstack = _fromnxfunction_seq(np.dstack) 

331stack = _fromnxfunction_seq(np.stack) 

332 

333hsplit = _fromnxfunction_single(np.hsplit) 

334diagflat = _fromnxfunction_single(np.diagflat) 

335 

336 

337#####-------------------------------------------------------------------------- 

338#---- 

339#####-------------------------------------------------------------------------- 

340def flatten_inplace(seq): 

341 """Flatten a sequence in place.""" 

342 k = 0 

343 while (k != len(seq)): 

344 while hasattr(seq[k], '__iter__'): 

345 seq[k:(k + 1)] = seq[k] 

346 k += 1 

347 return seq 

348 

349 

350def apply_along_axis(func1d, axis, arr, *args, **kwargs): 

351 """ 

352 (This docstring should be overwritten) 

353 """ 

354 arr = array(arr, copy=False, subok=True) 

355 nd = arr.ndim 

356 axis = normalize_axis_index(axis, nd) 

357 ind = [0] * (nd - 1) 

358 i = np.zeros(nd, 'O') 

359 indlist = list(range(nd)) 

360 indlist.remove(axis) 

361 i[axis] = slice(None, None) 

362 outshape = np.asarray(arr.shape).take(indlist) 

363 i.put(indlist, ind) 

364 res = func1d(arr[tuple(i.tolist())], *args, **kwargs) 

365 # if res is a number, then we have a smaller output array 

366 asscalar = np.isscalar(res) 

367 if not asscalar: 

368 try: 

369 len(res) 

370 except TypeError: 

371 asscalar = True 

372 # Note: we shouldn't set the dtype of the output from the first result 

373 # so we force the type to object, and build a list of dtypes. We'll 

374 # just take the largest, to avoid some downcasting 

375 dtypes = [] 

376 if asscalar: 

377 dtypes.append(np.asarray(res).dtype) 

378 outarr = zeros(outshape, object) 

379 outarr[tuple(ind)] = res 

380 Ntot = np.prod(outshape) 

381 k = 1 

382 while k < Ntot: 

383 # increment the index 

384 ind[-1] += 1 

385 n = -1 

386 while (ind[n] >= outshape[n]) and (n > (1 - nd)): 

387 ind[n - 1] += 1 

388 ind[n] = 0 

389 n -= 1 

390 i.put(indlist, ind) 

391 res = func1d(arr[tuple(i.tolist())], *args, **kwargs) 

392 outarr[tuple(ind)] = res 

393 dtypes.append(asarray(res).dtype) 

394 k += 1 

395 else: 

396 res = array(res, copy=False, subok=True) 

397 j = i.copy() 

398 j[axis] = ([slice(None, None)] * res.ndim) 

399 j.put(indlist, ind) 

400 Ntot = np.prod(outshape) 

401 holdshape = outshape 

402 outshape = list(arr.shape) 

403 outshape[axis] = res.shape 

404 dtypes.append(asarray(res).dtype) 

405 outshape = flatten_inplace(outshape) 

406 outarr = zeros(outshape, object) 

407 outarr[tuple(flatten_inplace(j.tolist()))] = res 

408 k = 1 

409 while k < Ntot: 

410 # increment the index 

411 ind[-1] += 1 

412 n = -1 

413 while (ind[n] >= holdshape[n]) and (n > (1 - nd)): 

414 ind[n - 1] += 1 

415 ind[n] = 0 

416 n -= 1 

417 i.put(indlist, ind) 

418 j.put(indlist, ind) 

419 res = func1d(arr[tuple(i.tolist())], *args, **kwargs) 

420 outarr[tuple(flatten_inplace(j.tolist()))] = res 

421 dtypes.append(asarray(res).dtype) 

422 k += 1 

423 max_dtypes = np.dtype(np.asarray(dtypes).max()) 

424 if not hasattr(arr, '_mask'): 

425 result = np.asarray(outarr, dtype=max_dtypes) 

426 else: 

427 result = asarray(outarr, dtype=max_dtypes) 

428 result.fill_value = ma.default_fill_value(result) 

429 return result 

430 

431 

432apply_along_axis.__doc__ = np.apply_along_axis.__doc__ 

433 

434 

435def apply_over_axes(func, a, axes): 

436 """ 

437 (This docstring will be overwritten) 

438 """ 

439 val = asarray(a) 

440 N = a.ndim 

441 if array(axes).ndim == 0: 

442 axes = (axes,) 

443 for axis in axes: 

444 if axis < 0: 

445 axis = N + axis 

446 args = (val, axis) 

447 res = func(*args) 

448 if res.ndim == val.ndim: 

449 val = res 

450 else: 

451 res = ma.expand_dims(res, axis) 

452 if res.ndim == val.ndim: 

453 val = res 

454 else: 

455 raise ValueError("function is not returning " 

456 "an array of the correct shape") 

457 return val 

458 

459 

460if apply_over_axes.__doc__ is not None: 

461 apply_over_axes.__doc__ = np.apply_over_axes.__doc__[ 

462 :np.apply_over_axes.__doc__.find('Notes')].rstrip() + \ 

463 """ 

464 

465 Examples 

466 -------- 

467 >>> import numpy as np 

468 >>> a = np.ma.arange(24).reshape(2,3,4) 

469 >>> a[:,0,1] = np.ma.masked 

470 >>> a[:,1,:] = np.ma.masked 

471 >>> a 

472 masked_array( 

473 data=[[[0, --, 2, 3], 

474 [--, --, --, --], 

475 [8, 9, 10, 11]], 

476 [[12, --, 14, 15], 

477 [--, --, --, --], 

478 [20, 21, 22, 23]]], 

479 mask=[[[False, True, False, False], 

480 [ True, True, True, True], 

481 [False, False, False, False]], 

482 [[False, True, False, False], 

483 [ True, True, True, True], 

484 [False, False, False, False]]], 

485 fill_value=999999) 

486 >>> np.ma.apply_over_axes(np.ma.sum, a, [0,2]) 

487 masked_array( 

488 data=[[[46], 

489 [--], 

490 [124]]], 

491 mask=[[[False], 

492 [ True], 

493 [False]]], 

494 fill_value=999999) 

495 

496 Tuple axis arguments to ufuncs are equivalent: 

497 

498 >>> np.ma.sum(a, axis=(0,2)).reshape((1,-1,1)) 

499 masked_array( 

500 data=[[[46], 

501 [--], 

502 [124]]], 

503 mask=[[[False], 

504 [ True], 

505 [False]]], 

506 fill_value=999999) 

507 """ 

508 

509 

510def average(a, axis=None, weights=None, returned=False, *, 

511 keepdims=np._NoValue): 

512 """ 

513 Return the weighted average of array over the given axis. 

514 

515 Parameters 

516 ---------- 

517 a : array_like 

518 Data to be averaged. 

519 Masked entries are not taken into account in the computation. 

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

521 Axis or axes along which to average `a`. The default, 

522 `axis=None`, will average over all of the elements of the input array. 

523 If axis is a tuple of ints, averaging is performed on all of the axes 

524 specified in the tuple instead of a single axis or all the axes as 

525 before. 

526 weights : array_like, optional 

527 An array of weights associated with the values in `a`. Each value in 

528 `a` contributes to the average according to its associated weight. 

529 The array of weights must be the same shape as `a` if no axis is 

530 specified, otherwise the weights must have dimensions and shape 

531 consistent with `a` along the specified axis. 

532 If `weights=None`, then all data in `a` are assumed to have a 

533 weight equal to one. 

534 The calculation is:: 

535 

536 avg = sum(a * weights) / sum(weights) 

537 

538 where the sum is over all included elements. 

539 The only constraint on the values of `weights` is that `sum(weights)` 

540 must not be 0. 

541 returned : bool, optional 

542 Flag indicating whether a tuple ``(result, sum of weights)`` 

543 should be returned as output (True), or just the result (False). 

544 Default is False. 

545 keepdims : bool, optional 

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

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

548 the result will broadcast correctly against the original `a`. 

549 *Note:* `keepdims` will not work with instances of `numpy.matrix` 

550 or other classes whose methods do not support `keepdims`. 

551 

552 .. versionadded:: 1.23.0 

553 

554 Returns 

555 ------- 

556 average, [sum_of_weights] : (tuple of) scalar or MaskedArray 

557 The average along the specified axis. When returned is `True`, 

558 return a tuple with the average as the first element and the sum 

559 of the weights as the second element. The return type is `np.float64` 

560 if `a` is of integer type and floats smaller than `float64`, or the 

561 input data-type, otherwise. If returned, `sum_of_weights` is always 

562 `float64`. 

563 

564 Raises 

565 ------ 

566 ZeroDivisionError 

567 When all weights along axis are zero. See `numpy.ma.average` for a 

568 version robust to this type of error. 

569 TypeError 

570 When `weights` does not have the same shape as `a`, and `axis=None`. 

571 ValueError 

572 When `weights` does not have dimensions and shape consistent with `a` 

573 along specified `axis`. 

574 

575 Examples 

576 -------- 

577 >>> import numpy as np 

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

579 >>> np.ma.average(a, weights=[3, 1, 0, 0]) 

580 1.25 

581 

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

583 >>> x 

584 masked_array( 

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

586 [2., 3.], 

587 [4., 5.]], 

588 mask=False, 

589 fill_value=1e+20) 

590 >>> data = np.arange(8).reshape((2, 2, 2)) 

591 >>> data 

592 array([[[0, 1], 

593 [2, 3]], 

594 [[4, 5], 

595 [6, 7]]]) 

596 >>> np.ma.average(data, axis=(0, 1), weights=[[1./4, 3./4], [1., 1./2]]) 

597 masked_array(data=[3.4, 4.4], 

598 mask=[False, False], 

599 fill_value=1e+20) 

600 >>> np.ma.average(data, axis=0, weights=[[1./4, 3./4], [1., 1./2]]) 

601 Traceback (most recent call last): 

602 ... 

603 ValueError: Shape of weights must be consistent 

604 with shape of a along specified axis. 

605 

606 >>> avg, sumweights = np.ma.average(x, axis=0, weights=[1, 2, 3], 

607 ... returned=True) 

608 >>> avg 

609 masked_array(data=[2.6666666666666665, 3.6666666666666665], 

610 mask=[False, False], 

611 fill_value=1e+20) 

612 

613 With ``keepdims=True``, the following result has shape (3, 1). 

614 

615 >>> np.ma.average(x, axis=1, keepdims=True) 

616 masked_array( 

617 data=[[0.5], 

618 [2.5], 

619 [4.5]], 

620 mask=False, 

621 fill_value=1e+20) 

622 """ 

623 a = asarray(a) 

624 m = getmask(a) 

625 

626 if axis is not None: 

627 axis = normalize_axis_tuple(axis, a.ndim, argname="axis") 

628 

629 if keepdims is np._NoValue: 

630 # Don't pass on the keepdims argument if one wasn't given. 

631 keepdims_kw = {} 

632 else: 

633 keepdims_kw = {'keepdims': keepdims} 

634 

635 if weights is None: 

636 avg = a.mean(axis, **keepdims_kw) 

637 scl = avg.dtype.type(a.count(axis)) 

638 else: 

639 wgt = asarray(weights) 

640 

641 if issubclass(a.dtype.type, (np.integer, np.bool)): 

642 result_dtype = np.result_type(a.dtype, wgt.dtype, 'f8') 

643 else: 

644 result_dtype = np.result_type(a.dtype, wgt.dtype) 

645 

646 # Sanity checks 

647 if a.shape != wgt.shape: 

648 if axis is None: 

649 raise TypeError( 

650 "Axis must be specified when shapes of a and weights " 

651 "differ.") 

652 if wgt.shape != tuple(a.shape[ax] for ax in axis): 

653 raise ValueError( 

654 "Shape of weights must be consistent with " 

655 "shape of a along specified axis.") 

656 

657 # setup wgt to broadcast along axis 

658 wgt = wgt.transpose(np.argsort(axis)) 

659 wgt = wgt.reshape(tuple((s if ax in axis else 1) 

660 for ax, s in enumerate(a.shape))) 

661 

662 if m is not nomask: 

663 wgt = wgt * (~a.mask) 

664 wgt.mask |= a.mask 

665 

666 scl = wgt.sum(axis=axis, dtype=result_dtype, **keepdims_kw) 

667 avg = np.multiply(a, wgt, 

668 dtype=result_dtype).sum(axis, **keepdims_kw) / scl 

669 

670 if returned: 

671 if scl.shape != avg.shape: 

672 scl = np.broadcast_to(scl, avg.shape).copy() 

673 return avg, scl 

674 else: 

675 return avg 

676 

677 

678def median(a, axis=None, out=None, overwrite_input=False, keepdims=False): 

679 """ 

680 Compute the median along the specified axis. 

681 

682 Returns the median of the array elements. 

683 

684 Parameters 

685 ---------- 

686 a : array_like 

687 Input array or object that can be converted to an array. 

688 axis : int, optional 

689 Axis along which the medians are computed. The default (None) is 

690 to compute the median along a flattened version of the array. 

691 out : ndarray, optional 

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

693 have the same shape and buffer length as the expected output 

694 but the type will be cast if necessary. 

695 overwrite_input : bool, optional 

696 If True, then allow use of memory of input array (a) for 

697 calculations. The input array will be modified by the call to 

698 median. This will save memory when you do not need to preserve 

699 the contents of the input array. Treat the input as undefined, 

700 but it will probably be fully or partially sorted. Default is 

701 False. Note that, if `overwrite_input` is True, and the input 

702 is not already an `ndarray`, an error will be raised. 

703 keepdims : bool, optional 

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

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

706 the result will broadcast correctly against the input array. 

707 

708 Returns 

709 ------- 

710 median : ndarray 

711 A new array holding the result is returned unless out is 

712 specified, in which case a reference to out is returned. 

713 Return data-type is `float64` for integers and floats smaller than 

714 `float64`, or the input data-type, otherwise. 

715 

716 See Also 

717 -------- 

718 mean 

719 

720 Notes 

721 ----- 

722 Given a vector ``V`` with ``N`` non masked values, the median of ``V`` 

723 is the middle value of a sorted copy of ``V`` (``Vs``) - i.e. 

724 ``Vs[(N-1)/2]``, when ``N`` is odd, or ``{Vs[N/2 - 1] + Vs[N/2]}/2`` 

725 when ``N`` is even. 

726 

727 Examples 

728 -------- 

729 >>> import numpy as np 

730 >>> x = np.ma.array(np.arange(8), mask=[0]*4 + [1]*4) 

731 >>> np.ma.median(x) 

732 1.5 

733 

734 >>> x = np.ma.array(np.arange(10).reshape(2, 5), mask=[0]*6 + [1]*4) 

735 >>> np.ma.median(x) 

736 2.5 

737 >>> np.ma.median(x, axis=-1, overwrite_input=True) 

738 masked_array(data=[2.0, 5.0], 

739 mask=[False, False], 

740 fill_value=1e+20) 

741 

742 """ 

743 if not hasattr(a, 'mask'): 

744 m = np.median(getdata(a, subok=True), axis=axis, 

745 out=out, overwrite_input=overwrite_input, 

746 keepdims=keepdims) 

747 if isinstance(m, np.ndarray) and 1 <= m.ndim: 

748 return masked_array(m, copy=False) 

749 else: 

750 return m 

751 

752 return _ureduce(a, func=_median, keepdims=keepdims, axis=axis, out=out, 

753 overwrite_input=overwrite_input) 

754 

755 

756def _median(a, axis=None, out=None, overwrite_input=False): 

757 # when an unmasked NaN is present return it, so we need to sort the NaN 

758 # values behind the mask 

759 if np.issubdtype(a.dtype, np.inexact): 

760 fill_value = np.inf 

761 else: 

762 fill_value = None 

763 if overwrite_input: 

764 if axis is None: 

765 asorted = a.ravel() 

766 asorted.sort(fill_value=fill_value) 

767 else: 

768 a.sort(axis=axis, fill_value=fill_value) 

769 asorted = a 

770 else: 

771 asorted = sort(a, axis=axis, fill_value=fill_value) 

772 

773 if axis is None: 

774 axis = 0 

775 else: 

776 axis = normalize_axis_index(axis, asorted.ndim) 

777 

778 if asorted.shape[axis] == 0: 

779 # for empty axis integer indices fail so use slicing to get same result 

780 # as median (which is mean of empty slice = nan) 

781 indexer = [slice(None)] * asorted.ndim 

782 indexer[axis] = slice(0, 0) 

783 indexer = tuple(indexer) 

784 return np.ma.mean(asorted[indexer], axis=axis, out=out) 

785 

786 if asorted.ndim == 1: 

787 idx, odd = divmod(count(asorted), 2) 

788 mid = asorted[idx + odd - 1:idx + 1] 

789 if np.issubdtype(asorted.dtype, np.inexact) and asorted.size > 0: 

790 # avoid inf / x = masked 

791 s = mid.sum(out=out) 

792 if not odd: 

793 s = np.true_divide(s, 2., casting='safe', out=out) 

794 s = np.lib._utils_impl._median_nancheck(asorted, s, axis) 

795 else: 

796 s = mid.mean(out=out) 

797 

798 # if result is masked either the input contained enough 

799 # minimum_fill_value so that it would be the median or all values 

800 # masked 

801 if np.ma.is_masked(s) and not np.all(asorted.mask): 

802 return np.ma.minimum_fill_value(asorted) 

803 return s 

804 

805 counts = count(asorted, axis=axis, keepdims=True) 

806 h = counts // 2 

807 

808 # duplicate high if odd number of elements so mean does nothing 

809 odd = counts % 2 == 1 

810 l = np.where(odd, h, h - 1) 

811 

812 lh = np.concatenate([l, h], axis=axis) 

813 

814 # get low and high median 

815 low_high = np.take_along_axis(asorted, lh, axis=axis) 

816 

817 def replace_masked(s): 

818 # Replace masked entries with minimum_full_value unless it all values 

819 # are masked. This is required as the sort order of values equal or 

820 # larger than the fill value is undefined and a valid value placed 

821 # elsewhere, e.g. [4, --, inf]. 

822 if np.ma.is_masked(s): 

823 rep = (~np.all(asorted.mask, axis=axis, keepdims=True)) & s.mask 

824 s.data[rep] = np.ma.minimum_fill_value(asorted) 

825 s.mask[rep] = False 

826 

827 replace_masked(low_high) 

828 

829 if np.issubdtype(asorted.dtype, np.inexact): 

830 # avoid inf / x = masked 

831 s = np.ma.sum(low_high, axis=axis, out=out) 

832 np.true_divide(s.data, 2., casting='unsafe', out=s.data) 

833 

834 s = np.lib._utils_impl._median_nancheck(asorted, s, axis) 

835 else: 

836 s = np.ma.mean(low_high, axis=axis, out=out) 

837 

838 return s 

839 

840 

841def compress_nd(x, axis=None): 

842 """Suppress slices from multiple dimensions which contain masked values. 

843 

844 Parameters 

845 ---------- 

846 x : array_like, MaskedArray 

847 The array to operate on. If not a MaskedArray instance (or if no array 

848 elements are masked), `x` is interpreted as a MaskedArray with `mask` 

849 set to `nomask`. 

850 axis : tuple of ints or int, optional 

851 Which dimensions to suppress slices from can be configured with this 

852 parameter. 

853 - If axis is a tuple of ints, those are the axes to suppress slices from. 

854 - If axis is an int, then that is the only axis to suppress slices from. 

855 - If axis is None, all axis are selected. 

856 

857 Returns 

858 ------- 

859 compress_array : ndarray 

860 The compressed array. 

861 

862 Examples 

863 -------- 

864 >>> import numpy as np 

865 >>> arr = [[1, 2], [3, 4]] 

866 >>> mask = [[0, 1], [0, 0]] 

867 >>> x = np.ma.array(arr, mask=mask) 

868 >>> np.ma.compress_nd(x, axis=0) 

869 array([[3, 4]]) 

870 >>> np.ma.compress_nd(x, axis=1) 

871 array([[1], 

872 [3]]) 

873 >>> np.ma.compress_nd(x) 

874 array([[3]]) 

875 

876 """ 

877 x = asarray(x) 

878 m = getmask(x) 

879 # Set axis to tuple of ints 

880 if axis is None: 

881 axis = tuple(range(x.ndim)) 

882 else: 

883 axis = normalize_axis_tuple(axis, x.ndim) 

884 

885 # Nothing is masked: return x 

886 if m is nomask or not m.any(): 

887 return x._data 

888 # All is masked: return empty 

889 if m.all(): 

890 return nxarray([]) 

891 # Filter elements through boolean indexing 

892 data = x._data 

893 for ax in axis: 

894 axes = tuple(list(range(ax)) + list(range(ax + 1, x.ndim))) 

895 data = data[(slice(None),) * ax + (~m.any(axis=axes),)] 

896 return data 

897 

898 

899def compress_rowcols(x, axis=None): 

900 """ 

901 Suppress the rows and/or columns of a 2-D array that contain 

902 masked values. 

903 

904 The suppression behavior is selected with the `axis` parameter. 

905 

906 - If axis is None, both rows and columns are suppressed. 

907 - If axis is 0, only rows are suppressed. 

908 - If axis is 1 or -1, only columns are suppressed. 

909 

910 Parameters 

911 ---------- 

912 x : array_like, MaskedArray 

913 The array to operate on. If not a MaskedArray instance (or if no array 

914 elements are masked), `x` is interpreted as a MaskedArray with 

915 `mask` set to `nomask`. Must be a 2D array. 

916 axis : int, optional 

917 Axis along which to perform the operation. Default is None. 

918 

919 Returns 

920 ------- 

921 compressed_array : ndarray 

922 The compressed array. 

923 

924 Examples 

925 -------- 

926 >>> import numpy as np 

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

928 ... [1, 0, 0], 

929 ... [0, 0, 0]]) 

930 >>> x 

931 masked_array( 

932 data=[[--, 1, 2], 

933 [--, 4, 5], 

934 [6, 7, 8]], 

935 mask=[[ True, False, False], 

936 [ True, False, False], 

937 [False, False, False]], 

938 fill_value=999999) 

939 

940 >>> np.ma.compress_rowcols(x) 

941 array([[7, 8]]) 

942 >>> np.ma.compress_rowcols(x, 0) 

943 array([[6, 7, 8]]) 

944 >>> np.ma.compress_rowcols(x, 1) 

945 array([[1, 2], 

946 [4, 5], 

947 [7, 8]]) 

948 

949 """ 

950 if asarray(x).ndim != 2: 

951 raise NotImplementedError("compress_rowcols works for 2D arrays only.") 

952 return compress_nd(x, axis=axis) 

953 

954 

955def compress_rows(a): 

956 """ 

957 Suppress whole rows of a 2-D array that contain masked values. 

958 

959 This is equivalent to ``np.ma.compress_rowcols(a, 0)``, see 

960 `compress_rowcols` for details. 

961 

962 Parameters 

963 ---------- 

964 x : array_like, MaskedArray 

965 The array to operate on. If not a MaskedArray instance (or if no array 

966 elements are masked), `x` is interpreted as a MaskedArray with 

967 `mask` set to `nomask`. Must be a 2D array. 

968 

969 Returns 

970 ------- 

971 compressed_array : ndarray 

972 The compressed array. 

973 

974 See Also 

975 -------- 

976 compress_rowcols 

977 

978 Examples 

979 -------- 

980 >>> import numpy as np 

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

982 ... [1, 0, 0], 

983 ... [0, 0, 0]]) 

984 >>> np.ma.compress_rows(a) 

985 array([[6, 7, 8]]) 

986 

987 """ 

988 a = asarray(a) 

989 if a.ndim != 2: 

990 raise NotImplementedError("compress_rows works for 2D arrays only.") 

991 return compress_rowcols(a, 0) 

992 

993 

994def compress_cols(a): 

995 """ 

996 Suppress whole columns of a 2-D array that contain masked values. 

997 

998 This is equivalent to ``np.ma.compress_rowcols(a, 1)``, see 

999 `compress_rowcols` for details. 

1000 

1001 Parameters 

1002 ---------- 

1003 x : array_like, MaskedArray 

1004 The array to operate on. If not a MaskedArray instance (or if no array 

1005 elements are masked), `x` is interpreted as a MaskedArray with 

1006 `mask` set to `nomask`. Must be a 2D array. 

1007 

1008 Returns 

1009 ------- 

1010 compressed_array : ndarray 

1011 The compressed array. 

1012 

1013 See Also 

1014 -------- 

1015 compress_rowcols 

1016 

1017 Examples 

1018 -------- 

1019 >>> import numpy as np 

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

1021 ... [1, 0, 0], 

1022 ... [0, 0, 0]]) 

1023 >>> np.ma.compress_cols(a) 

1024 array([[1, 2], 

1025 [4, 5], 

1026 [7, 8]]) 

1027 

1028 """ 

1029 a = asarray(a) 

1030 if a.ndim != 2: 

1031 raise NotImplementedError("compress_cols works for 2D arrays only.") 

1032 return compress_rowcols(a, 1) 

1033 

1034 

1035def mask_rowcols(a, axis=None): 

1036 """ 

1037 Mask rows and/or columns of a 2D array that contain masked values. 

1038 

1039 Mask whole rows and/or columns of a 2D array that contain 

1040 masked values. The masking behavior is selected using the 

1041 `axis` parameter. 

1042 

1043 - If `axis` is None, rows *and* columns are masked. 

1044 - If `axis` is 0, only rows are masked. 

1045 - If `axis` is 1 or -1, only columns are masked. 

1046 

1047 Parameters 

1048 ---------- 

1049 a : array_like, MaskedArray 

1050 The array to mask. If not a MaskedArray instance (or if no array 

1051 elements are masked), the result is a MaskedArray with `mask` set 

1052 to `nomask` (False). Must be a 2D array. 

1053 axis : int, optional 

1054 Axis along which to perform the operation. If None, applies to a 

1055 flattened version of the array. 

1056 

1057 Returns 

1058 ------- 

1059 a : MaskedArray 

1060 A modified version of the input array, masked depending on the value 

1061 of the `axis` parameter. 

1062 

1063 Raises 

1064 ------ 

1065 NotImplementedError 

1066 If input array `a` is not 2D. 

1067 

1068 See Also 

1069 -------- 

1070 mask_rows : Mask rows of a 2D array that contain masked values. 

1071 mask_cols : Mask cols of a 2D array that contain masked values. 

1072 masked_where : Mask where a condition is met. 

1073 

1074 Notes 

1075 ----- 

1076 The input array's mask is modified by this function. 

1077 

1078 Examples 

1079 -------- 

1080 >>> import numpy as np 

1081 >>> a = np.zeros((3, 3), dtype=int) 

1082 >>> a[1, 1] = 1 

1083 >>> a 

1084 array([[0, 0, 0], 

1085 [0, 1, 0], 

1086 [0, 0, 0]]) 

1087 >>> a = np.ma.masked_equal(a, 1) 

1088 >>> a 

1089 masked_array( 

1090 data=[[0, 0, 0], 

1091 [0, --, 0], 

1092 [0, 0, 0]], 

1093 mask=[[False, False, False], 

1094 [False, True, False], 

1095 [False, False, False]], 

1096 fill_value=1) 

1097 >>> np.ma.mask_rowcols(a) 

1098 masked_array( 

1099 data=[[0, --, 0], 

1100 [--, --, --], 

1101 [0, --, 0]], 

1102 mask=[[False, True, False], 

1103 [ True, True, True], 

1104 [False, True, False]], 

1105 fill_value=1) 

1106 

1107 """ 

1108 a = array(a, subok=False) 

1109 if a.ndim != 2: 

1110 raise NotImplementedError("mask_rowcols works for 2D arrays only.") 

1111 m = getmask(a) 

1112 # Nothing is masked: return a 

1113 if m is nomask or not m.any(): 

1114 return a 

1115 maskedval = m.nonzero() 

1116 a._mask = a._mask.copy() 

1117 if not axis: 

1118 a[np.unique(maskedval[0])] = masked 

1119 if axis in [None, 1, -1]: 

1120 a[:, np.unique(maskedval[1])] = masked 

1121 return a 

1122 

1123 

1124def mask_rows(a, axis=np._NoValue): 

1125 """ 

1126 Mask rows of a 2D array that contain masked values. 

1127 

1128 This function is a shortcut to ``mask_rowcols`` with `axis` equal to 0. 

1129 

1130 See Also 

1131 -------- 

1132 mask_rowcols : Mask rows and/or columns of a 2D array. 

1133 masked_where : Mask where a condition is met. 

1134 

1135 Examples 

1136 -------- 

1137 >>> import numpy as np 

1138 >>> a = np.zeros((3, 3), dtype=int) 

1139 >>> a[1, 1] = 1 

1140 >>> a 

1141 array([[0, 0, 0], 

1142 [0, 1, 0], 

1143 [0, 0, 0]]) 

1144 >>> a = np.ma.masked_equal(a, 1) 

1145 >>> a 

1146 masked_array( 

1147 data=[[0, 0, 0], 

1148 [0, --, 0], 

1149 [0, 0, 0]], 

1150 mask=[[False, False, False], 

1151 [False, True, False], 

1152 [False, False, False]], 

1153 fill_value=1) 

1154 

1155 >>> np.ma.mask_rows(a) 

1156 masked_array( 

1157 data=[[0, 0, 0], 

1158 [--, --, --], 

1159 [0, 0, 0]], 

1160 mask=[[False, False, False], 

1161 [ True, True, True], 

1162 [False, False, False]], 

1163 fill_value=1) 

1164 

1165 """ 

1166 if axis is not np._NoValue: 

1167 # remove the axis argument when this deprecation expires 

1168 # NumPy 1.18.0, 2019-11-28 

1169 warnings.warn( 

1170 "The axis argument has always been ignored, in future passing it " 

1171 "will raise TypeError", DeprecationWarning, stacklevel=2) 

1172 return mask_rowcols(a, 0) 

1173 

1174 

1175def mask_cols(a, axis=np._NoValue): 

1176 """ 

1177 Mask columns of a 2D array that contain masked values. 

1178 

1179 This function is a shortcut to ``mask_rowcols`` with `axis` equal to 1. 

1180 

1181 See Also 

1182 -------- 

1183 mask_rowcols : Mask rows and/or columns of a 2D array. 

1184 masked_where : Mask where a condition is met. 

1185 

1186 Examples 

1187 -------- 

1188 >>> import numpy as np 

1189 >>> a = np.zeros((3, 3), dtype=int) 

1190 >>> a[1, 1] = 1 

1191 >>> a 

1192 array([[0, 0, 0], 

1193 [0, 1, 0], 

1194 [0, 0, 0]]) 

1195 >>> a = np.ma.masked_equal(a, 1) 

1196 >>> a 

1197 masked_array( 

1198 data=[[0, 0, 0], 

1199 [0, --, 0], 

1200 [0, 0, 0]], 

1201 mask=[[False, False, False], 

1202 [False, True, False], 

1203 [False, False, False]], 

1204 fill_value=1) 

1205 >>> np.ma.mask_cols(a) 

1206 masked_array( 

1207 data=[[0, --, 0], 

1208 [0, --, 0], 

1209 [0, --, 0]], 

1210 mask=[[False, True, False], 

1211 [False, True, False], 

1212 [False, True, False]], 

1213 fill_value=1) 

1214 

1215 """ 

1216 if axis is not np._NoValue: 

1217 # remove the axis argument when this deprecation expires 

1218 # NumPy 1.18.0, 2019-11-28 

1219 warnings.warn( 

1220 "The axis argument has always been ignored, in future passing it " 

1221 "will raise TypeError", DeprecationWarning, stacklevel=2) 

1222 return mask_rowcols(a, 1) 

1223 

1224 

1225#####-------------------------------------------------------------------------- 

1226#---- --- arraysetops --- 

1227#####-------------------------------------------------------------------------- 

1228 

1229def ediff1d(arr, to_end=None, to_begin=None): 

1230 """ 

1231 Compute the differences between consecutive elements of an array. 

1232 

1233 This function is the equivalent of `numpy.ediff1d` that takes masked 

1234 values into account, see `numpy.ediff1d` for details. 

1235 

1236 See Also 

1237 -------- 

1238 numpy.ediff1d : Equivalent function for ndarrays. 

1239 

1240 Examples 

1241 -------- 

1242 >>> import numpy as np 

1243 >>> arr = np.ma.array([1, 2, 4, 7, 0]) 

1244 >>> np.ma.ediff1d(arr) 

1245 masked_array(data=[ 1, 2, 3, -7], 

1246 mask=False, 

1247 fill_value=999999) 

1248 

1249 """ 

1250 arr = ma.asanyarray(arr).flat 

1251 ed = arr[1:] - arr[:-1] 

1252 arrays = [ed] 

1253 # 

1254 if to_begin is not None: 

1255 arrays.insert(0, to_begin) 

1256 if to_end is not None: 

1257 arrays.append(to_end) 

1258 # 

1259 if len(arrays) != 1: 

1260 # We'll save ourselves a copy of a potentially large array in the common 

1261 # case where neither to_begin or to_end was given. 

1262 ed = hstack(arrays) 

1263 # 

1264 return ed 

1265 

1266 

1267def unique(ar1, return_index=False, return_inverse=False): 

1268 """ 

1269 Finds the unique elements of an array. 

1270 

1271 Masked values are considered the same element (masked). The output array 

1272 is always a masked array. See `numpy.unique` for more details. 

1273 

1274 See Also 

1275 -------- 

1276 numpy.unique : Equivalent function for ndarrays. 

1277 

1278 Examples 

1279 -------- 

1280 >>> import numpy as np 

1281 >>> a = [1, 2, 1000, 2, 3] 

1282 >>> mask = [0, 0, 1, 0, 0] 

1283 >>> masked_a = np.ma.masked_array(a, mask) 

1284 >>> masked_a 

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

1286 mask=[False, False, True, False, False], 

1287 fill_value=999999) 

1288 >>> np.ma.unique(masked_a) 

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

1290 mask=[False, False, False, True], 

1291 fill_value=999999) 

1292 >>> np.ma.unique(masked_a, return_index=True) 

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

1294 mask=[False, False, False, True], 

1295 fill_value=999999), array([0, 1, 4, 2])) 

1296 >>> np.ma.unique(masked_a, return_inverse=True) 

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

1298 mask=[False, False, False, True], 

1299 fill_value=999999), array([0, 1, 3, 1, 2])) 

1300 >>> np.ma.unique(masked_a, return_index=True, return_inverse=True) 

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

1302 mask=[False, False, False, True], 

1303 fill_value=999999), array([0, 1, 4, 2]), array([0, 1, 3, 1, 2])) 

1304 """ 

1305 output = np.unique(ar1, 

1306 return_index=return_index, 

1307 return_inverse=return_inverse) 

1308 if isinstance(output, tuple): 

1309 output = list(output) 

1310 output[0] = output[0].view(MaskedArray) 

1311 output = tuple(output) 

1312 else: 

1313 output = output.view(MaskedArray) 

1314 return output 

1315 

1316 

1317def intersect1d(ar1, ar2, assume_unique=False): 

1318 """ 

1319 Returns the unique elements common to both arrays. 

1320 

1321 Masked values are considered equal one to the other. 

1322 The output is always a masked array. 

1323 

1324 See `numpy.intersect1d` for more details. 

1325 

1326 See Also 

1327 -------- 

1328 numpy.intersect1d : Equivalent function for ndarrays. 

1329 

1330 Examples 

1331 -------- 

1332 >>> import numpy as np 

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

1334 >>> y = np.ma.array([3, 1, 1, 1], mask=[0, 0, 0, 1]) 

1335 >>> np.ma.intersect1d(x, y) 

1336 masked_array(data=[1, 3, --], 

1337 mask=[False, False, True], 

1338 fill_value=999999) 

1339 

1340 """ 

1341 if assume_unique: 

1342 aux = ma.concatenate((ar1, ar2)) 

1343 else: 

1344 # Might be faster than unique( intersect1d( ar1, ar2 ) )? 

1345 aux = ma.concatenate((unique(ar1), unique(ar2))) 

1346 aux.sort() 

1347 return aux[:-1][aux[1:] == aux[:-1]] 

1348 

1349 

1350def setxor1d(ar1, ar2, assume_unique=False): 

1351 """ 

1352 Set exclusive-or of 1-D arrays with unique elements. 

1353 

1354 The output is always a masked array. See `numpy.setxor1d` for more details. 

1355 

1356 See Also 

1357 -------- 

1358 numpy.setxor1d : Equivalent function for ndarrays. 

1359 

1360 Examples 

1361 -------- 

1362 >>> import numpy as np 

1363 >>> ar1 = np.ma.array([1, 2, 3, 2, 4]) 

1364 >>> ar2 = np.ma.array([2, 3, 5, 7, 5]) 

1365 >>> np.ma.setxor1d(ar1, ar2) 

1366 masked_array(data=[1, 4, 5, 7], 

1367 mask=False, 

1368 fill_value=999999) 

1369 

1370 """ 

1371 if not assume_unique: 

1372 ar1 = unique(ar1) 

1373 ar2 = unique(ar2) 

1374 

1375 aux = ma.concatenate((ar1, ar2), axis=None) 

1376 if aux.size == 0: 

1377 return aux 

1378 aux.sort() 

1379 auxf = aux.filled() 

1380# flag = ediff1d( aux, to_end = 1, to_begin = 1 ) == 0 

1381 flag = ma.concatenate(([True], (auxf[1:] != auxf[:-1]), [True])) 

1382# flag2 = ediff1d( flag ) == 0 

1383 flag2 = (flag[1:] == flag[:-1]) 

1384 return aux[flag2] 

1385 

1386 

1387def in1d(ar1, ar2, assume_unique=False, invert=False): 

1388 """ 

1389 Test whether each element of an array is also present in a second 

1390 array. 

1391 

1392 The output is always a masked array. 

1393 

1394 We recommend using :func:`isin` instead of `in1d` for new code. 

1395 

1396 See Also 

1397 -------- 

1398 isin : Version of this function that preserves the shape of ar1. 

1399 

1400 Examples 

1401 -------- 

1402 >>> import numpy as np 

1403 >>> ar1 = np.ma.array([0, 1, 2, 5, 0]) 

1404 >>> ar2 = [0, 2] 

1405 >>> np.ma.in1d(ar1, ar2) 

1406 masked_array(data=[ True, False, True, False, True], 

1407 mask=False, 

1408 fill_value=True) 

1409 

1410 """ 

1411 if not assume_unique: 

1412 ar1, rev_idx = unique(ar1, return_inverse=True) 

1413 ar2 = unique(ar2) 

1414 

1415 ar = ma.concatenate((ar1, ar2)) 

1416 # We need this to be a stable sort, so always use 'mergesort' 

1417 # here. The values from the first array should always come before 

1418 # the values from the second array. 

1419 order = ar.argsort(kind='mergesort') 

1420 sar = ar[order] 

1421 if invert: 

1422 bool_ar = (sar[1:] != sar[:-1]) 

1423 else: 

1424 bool_ar = (sar[1:] == sar[:-1]) 

1425 flag = ma.concatenate((bool_ar, [invert])) 

1426 indx = order.argsort(kind='mergesort')[:len(ar1)] 

1427 

1428 if assume_unique: 

1429 return flag[indx] 

1430 else: 

1431 return flag[indx][rev_idx] 

1432 

1433 

1434def isin(element, test_elements, assume_unique=False, invert=False): 

1435 """ 

1436 Calculates `element in test_elements`, broadcasting over 

1437 `element` only. 

1438 

1439 The output is always a masked array of the same shape as `element`. 

1440 See `numpy.isin` for more details. 

1441 

1442 See Also 

1443 -------- 

1444 in1d : Flattened version of this function. 

1445 numpy.isin : Equivalent function for ndarrays. 

1446 

1447 Examples 

1448 -------- 

1449 >>> import numpy as np 

1450 >>> element = np.ma.array([1, 2, 3, 4, 5, 6]) 

1451 >>> test_elements = [0, 2] 

1452 >>> np.ma.isin(element, test_elements) 

1453 masked_array(data=[False, True, False, False, False, False], 

1454 mask=False, 

1455 fill_value=True) 

1456 

1457 """ 

1458 element = ma.asarray(element) 

1459 return in1d(element, test_elements, assume_unique=assume_unique, 

1460 invert=invert).reshape(element.shape) 

1461 

1462 

1463def union1d(ar1, ar2): 

1464 """ 

1465 Union of two arrays. 

1466 

1467 The output is always a masked array. See `numpy.union1d` for more details. 

1468 

1469 See Also 

1470 -------- 

1471 numpy.union1d : Equivalent function for ndarrays. 

1472 

1473 Examples 

1474 -------- 

1475 >>> import numpy as np 

1476 >>> ar1 = np.ma.array([1, 2, 3, 4]) 

1477 >>> ar2 = np.ma.array([3, 4, 5, 6]) 

1478 >>> np.ma.union1d(ar1, ar2) 

1479 masked_array(data=[1, 2, 3, 4, 5, 6], 

1480 mask=False, 

1481 fill_value=999999) 

1482 

1483 """ 

1484 return unique(ma.concatenate((ar1, ar2), axis=None)) 

1485 

1486 

1487def setdiff1d(ar1, ar2, assume_unique=False): 

1488 """ 

1489 Set difference of 1D arrays with unique elements. 

1490 

1491 The output is always a masked array. See `numpy.setdiff1d` for more 

1492 details. 

1493 

1494 See Also 

1495 -------- 

1496 numpy.setdiff1d : Equivalent function for ndarrays. 

1497 

1498 Examples 

1499 -------- 

1500 >>> import numpy as np 

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

1502 >>> np.ma.setdiff1d(x, [1, 2]) 

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

1504 mask=[False, True], 

1505 fill_value=999999) 

1506 

1507 """ 

1508 if assume_unique: 

1509 ar1 = ma.asarray(ar1).ravel() 

1510 else: 

1511 ar1 = unique(ar1) 

1512 ar2 = unique(ar2) 

1513 return ar1[in1d(ar1, ar2, assume_unique=True, invert=True)] 

1514 

1515 

1516############################################################################### 

1517# Covariance # 

1518############################################################################### 

1519 

1520 

1521def _covhelper(x, y=None, rowvar=True, allow_masked=True): 

1522 """ 

1523 Private function for the computation of covariance and correlation 

1524 coefficients. 

1525 

1526 """ 

1527 x = ma.array(x, ndmin=2, copy=True, dtype=float) 

1528 xmask = ma.getmaskarray(x) 

1529 # Quick exit if we can't process masked data 

1530 if not allow_masked and xmask.any(): 

1531 raise ValueError("Cannot process masked data.") 

1532 # 

1533 if x.shape[0] == 1: 

1534 rowvar = True 

1535 # Make sure that rowvar is either 0 or 1 

1536 rowvar = int(bool(rowvar)) 

1537 axis = 1 - rowvar 

1538 if rowvar: 

1539 tup = (slice(None), None) 

1540 else: 

1541 tup = (None, slice(None)) 

1542 # 

1543 if y is None: 

1544 # Check if we can guarantee that the integers in the (N - ddof) 

1545 # normalisation can be accurately represented with single-precision 

1546 # before computing the dot product. 

1547 if x.shape[0] > 2 ** 24 or x.shape[1] > 2 ** 24: 

1548 xnm_dtype = np.float64 

1549 else: 

1550 xnm_dtype = np.float32 

1551 xnotmask = np.logical_not(xmask).astype(xnm_dtype) 

1552 else: 

1553 y = array(y, copy=False, ndmin=2, dtype=float) 

1554 ymask = ma.getmaskarray(y) 

1555 if not allow_masked and ymask.any(): 

1556 raise ValueError("Cannot process masked data.") 

1557 if xmask.any() or ymask.any(): 

1558 if y.shape == x.shape: 

1559 # Define some common mask 

1560 common_mask = np.logical_or(xmask, ymask) 

1561 if common_mask is not nomask: 

1562 xmask = x._mask = y._mask = ymask = common_mask 

1563 x._sharedmask = False 

1564 y._sharedmask = False 

1565 x = ma.concatenate((x, y), axis) 

1566 # Check if we can guarantee that the integers in the (N - ddof) 

1567 # normalisation can be accurately represented with single-precision 

1568 # before computing the dot product. 

1569 if x.shape[0] > 2 ** 24 or x.shape[1] > 2 ** 24: 

1570 xnm_dtype = np.float64 

1571 else: 

1572 xnm_dtype = np.float32 

1573 xnotmask = np.logical_not(np.concatenate((xmask, ymask), axis)).astype( 

1574 xnm_dtype 

1575 ) 

1576 x -= x.mean(axis=rowvar)[tup] 

1577 return (x, xnotmask, rowvar) 

1578 

1579 

1580def cov(x, y=None, rowvar=True, bias=False, allow_masked=True, ddof=None): 

1581 """ 

1582 Estimate the covariance matrix. 

1583 

1584 Except for the handling of missing data this function does the same as 

1585 `numpy.cov`. For more details and examples, see `numpy.cov`. 

1586 

1587 By default, masked values are recognized as such. If `x` and `y` have the 

1588 same shape, a common mask is allocated: if ``x[i,j]`` is masked, then 

1589 ``y[i,j]`` will also be masked. 

1590 Setting `allow_masked` to False will raise an exception if values are 

1591 missing in either of the input arrays. 

1592 

1593 Parameters 

1594 ---------- 

1595 x : array_like 

1596 A 1-D or 2-D array containing multiple variables and observations. 

1597 Each row of `x` represents a variable, and each column a single 

1598 observation of all those variables. Also see `rowvar` below. 

1599 y : array_like, optional 

1600 An additional set of variables and observations. `y` has the same 

1601 shape as `x`. 

1602 rowvar : bool, optional 

1603 If `rowvar` is True (default), then each row represents a 

1604 variable, with observations in the columns. Otherwise, the relationship 

1605 is transposed: each column represents a variable, while the rows 

1606 contain observations. 

1607 bias : bool, optional 

1608 Default normalization (False) is by ``(N-1)``, where ``N`` is the 

1609 number of observations given (unbiased estimate). If `bias` is True, 

1610 then normalization is by ``N``. This keyword can be overridden by 

1611 the keyword ``ddof`` in numpy versions >= 1.5. 

1612 allow_masked : bool, optional 

1613 If True, masked values are propagated pair-wise: if a value is masked 

1614 in `x`, the corresponding value is masked in `y`. 

1615 If False, raises a `ValueError` exception when some values are missing. 

1616 ddof : {None, int}, optional 

1617 If not ``None`` normalization is by ``(N - ddof)``, where ``N`` is 

1618 the number of observations; this overrides the value implied by 

1619 ``bias``. The default value is ``None``. 

1620 

1621 Raises 

1622 ------ 

1623 ValueError 

1624 Raised if some values are missing and `allow_masked` is False. 

1625 

1626 See Also 

1627 -------- 

1628 numpy.cov 

1629 

1630 Examples 

1631 -------- 

1632 >>> import numpy as np 

1633 >>> x = np.ma.array([[0, 1], [1, 1]], mask=[0, 1, 0, 1]) 

1634 >>> y = np.ma.array([[1, 0], [0, 1]], mask=[0, 0, 1, 1]) 

1635 >>> np.ma.cov(x, y) 

1636 masked_array( 

1637 data=[[--, --, --, --], 

1638 [--, --, --, --], 

1639 [--, --, --, --], 

1640 [--, --, --, --]], 

1641 mask=[[ True, True, True, True], 

1642 [ True, True, True, True], 

1643 [ True, True, True, True], 

1644 [ True, True, True, True]], 

1645 fill_value=1e+20, 

1646 dtype=float64) 

1647 

1648 """ 

1649 # Check inputs 

1650 if ddof is not None and ddof != int(ddof): 

1651 raise ValueError("ddof must be an integer") 

1652 # Set up ddof 

1653 if ddof is None: 

1654 if bias: 

1655 ddof = 0 

1656 else: 

1657 ddof = 1 

1658 

1659 (x, xnotmask, rowvar) = _covhelper(x, y, rowvar, allow_masked) 

1660 if not rowvar: 

1661 fact = np.dot(xnotmask.T, xnotmask) - ddof 

1662 mask = np.less_equal(fact, 0, dtype=bool) 

1663 with np.errstate(divide="ignore", invalid="ignore"): 

1664 data = np.dot(filled(x.T, 0), filled(x.conj(), 0)) / fact 

1665 result = ma.array(data, mask=mask).squeeze() 

1666 else: 

1667 fact = np.dot(xnotmask, xnotmask.T) - ddof 

1668 mask = np.less_equal(fact, 0, dtype=bool) 

1669 with np.errstate(divide="ignore", invalid="ignore"): 

1670 data = np.dot(filled(x, 0), filled(x.T.conj(), 0)) / fact 

1671 result = ma.array(data, mask=mask).squeeze() 

1672 return result 

1673 

1674 

1675def corrcoef(x, y=None, rowvar=True, allow_masked=True, 

1676 ): 

1677 """ 

1678 Return Pearson product-moment correlation coefficients. 

1679 

1680 Except for the handling of missing data this function does the same as 

1681 `numpy.corrcoef`. For more details and examples, see `numpy.corrcoef`. 

1682 

1683 Parameters 

1684 ---------- 

1685 x : array_like 

1686 A 1-D or 2-D array containing multiple variables and observations. 

1687 Each row of `x` represents a variable, and each column a single 

1688 observation of all those variables. Also see `rowvar` below. 

1689 y : array_like, optional 

1690 An additional set of variables and observations. `y` has the same 

1691 shape as `x`. 

1692 rowvar : bool, optional 

1693 If `rowvar` is True (default), then each row represents a 

1694 variable, with observations in the columns. Otherwise, the relationship 

1695 is transposed: each column represents a variable, while the rows 

1696 contain observations. 

1697 allow_masked : bool, optional 

1698 If True, masked values are propagated pair-wise: if a value is masked 

1699 in `x`, the corresponding value is masked in `y`. 

1700 If False, raises an exception. Because `bias` is deprecated, this 

1701 argument needs to be treated as keyword only to avoid a warning. 

1702 

1703 See Also 

1704 -------- 

1705 numpy.corrcoef : Equivalent function in top-level NumPy module. 

1706 cov : Estimate the covariance matrix. 

1707 

1708 Examples 

1709 -------- 

1710 >>> import numpy as np 

1711 >>> x = np.ma.array([[0, 1], [1, 1]], mask=[0, 1, 0, 1]) 

1712 >>> np.ma.corrcoef(x) 

1713 masked_array( 

1714 data=[[--, --], 

1715 [--, --]], 

1716 mask=[[ True, True], 

1717 [ True, True]], 

1718 fill_value=1e+20, 

1719 dtype=float64) 

1720 

1721 """ 

1722 # Estimate the covariance matrix. 

1723 corr = cov(x, y, rowvar, allow_masked=allow_masked) 

1724 # The non-masked version returns a masked value for a scalar. 

1725 try: 

1726 std = ma.sqrt(ma.diagonal(corr)) 

1727 except ValueError: 

1728 return ma.MaskedConstant() 

1729 corr /= ma.multiply.outer(std, std) 

1730 return corr 

1731 

1732#####-------------------------------------------------------------------------- 

1733#---- --- Concatenation helpers --- 

1734#####-------------------------------------------------------------------------- 

1735 

1736class MAxisConcatenator(AxisConcatenator): 

1737 """ 

1738 Translate slice objects to concatenation along an axis. 

1739 

1740 For documentation on usage, see `mr_class`. 

1741 

1742 See Also 

1743 -------- 

1744 mr_class 

1745 

1746 """ 

1747 __slots__ = () 

1748 

1749 concatenate = staticmethod(concatenate) 

1750 

1751 @classmethod 

1752 def makemat(cls, arr): 

1753 # There used to be a view as np.matrix here, but we may eventually 

1754 # deprecate that class. In preparation, we use the unmasked version 

1755 # to construct the matrix (with copy=False for backwards compatibility 

1756 # with the .view) 

1757 data = super().makemat(arr.data, copy=False) 

1758 return array(data, mask=arr.mask) 

1759 

1760 def __getitem__(self, key): 

1761 # matrix builder syntax, like 'a, b; c, d' 

1762 if isinstance(key, str): 

1763 raise MAError("Unavailable for masked array.") 

1764 

1765 return super().__getitem__(key) 

1766 

1767 

1768class mr_class(MAxisConcatenator): 

1769 """ 

1770 Translate slice objects to concatenation along the first axis. 

1771 

1772 This is the masked array version of `r_`. 

1773 

1774 See Also 

1775 -------- 

1776 r_ 

1777 

1778 Examples 

1779 -------- 

1780 >>> import numpy as np 

1781 >>> np.ma.mr_[np.ma.array([1,2,3]), 0, 0, np.ma.array([4,5,6])] 

1782 masked_array(data=[1, 2, 3, ..., 4, 5, 6], 

1783 mask=False, 

1784 fill_value=999999) 

1785 

1786 """ 

1787 __slots__ = () 

1788 

1789 def __init__(self): 

1790 MAxisConcatenator.__init__(self, 0) 

1791 

1792 

1793mr_ = mr_class() 

1794 

1795 

1796#####-------------------------------------------------------------------------- 

1797#---- Find unmasked data --- 

1798#####-------------------------------------------------------------------------- 

1799 

1800def ndenumerate(a, compressed=True): 

1801 """ 

1802 Multidimensional index iterator. 

1803 

1804 Return an iterator yielding pairs of array coordinates and values, 

1805 skipping elements that are masked. With `compressed=False`, 

1806 `ma.masked` is yielded as the value of masked elements. This 

1807 behavior differs from that of `numpy.ndenumerate`, which yields the 

1808 value of the underlying data array. 

1809 

1810 Notes 

1811 ----- 

1812 .. versionadded:: 1.23.0 

1813 

1814 Parameters 

1815 ---------- 

1816 a : array_like 

1817 An array with (possibly) masked elements. 

1818 compressed : bool, optional 

1819 If True (default), masked elements are skipped. 

1820 

1821 See Also 

1822 -------- 

1823 numpy.ndenumerate : Equivalent function ignoring any mask. 

1824 

1825 Examples 

1826 -------- 

1827 >>> import numpy as np 

1828 >>> a = np.ma.arange(9).reshape((3, 3)) 

1829 >>> a[1, 0] = np.ma.masked 

1830 >>> a[1, 2] = np.ma.masked 

1831 >>> a[2, 1] = np.ma.masked 

1832 >>> a 

1833 masked_array( 

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

1835 [--, 4, --], 

1836 [6, --, 8]], 

1837 mask=[[False, False, False], 

1838 [ True, False, True], 

1839 [False, True, False]], 

1840 fill_value=999999) 

1841 >>> for index, x in np.ma.ndenumerate(a): 

1842 ... print(index, x) 

1843 (0, 0) 0 

1844 (0, 1) 1 

1845 (0, 2) 2 

1846 (1, 1) 4 

1847 (2, 0) 6 

1848 (2, 2) 8 

1849 

1850 >>> for index, x in np.ma.ndenumerate(a, compressed=False): 

1851 ... print(index, x) 

1852 (0, 0) 0 

1853 (0, 1) 1 

1854 (0, 2) 2 

1855 (1, 0) -- 

1856 (1, 1) 4 

1857 (1, 2) -- 

1858 (2, 0) 6 

1859 (2, 1) -- 

1860 (2, 2) 8 

1861 """ 

1862 for it, mask in zip(np.ndenumerate(a), getmaskarray(a).flat): 

1863 if not mask: 

1864 yield it 

1865 elif not compressed: 

1866 yield it[0], masked 

1867 

1868 

1869def flatnotmasked_edges(a): 

1870 """ 

1871 Find the indices of the first and last unmasked values. 

1872 

1873 Expects a 1-D `MaskedArray`, returns None if all values are masked. 

1874 

1875 Parameters 

1876 ---------- 

1877 a : array_like 

1878 Input 1-D `MaskedArray` 

1879 

1880 Returns 

1881 ------- 

1882 edges : ndarray or None 

1883 The indices of first and last non-masked value in the array. 

1884 Returns None if all values are masked. 

1885 

1886 See Also 

1887 -------- 

1888 flatnotmasked_contiguous, notmasked_contiguous, notmasked_edges 

1889 clump_masked, clump_unmasked 

1890 

1891 Notes 

1892 ----- 

1893 Only accepts 1-D arrays. 

1894 

1895 Examples 

1896 -------- 

1897 >>> import numpy as np 

1898 >>> a = np.ma.arange(10) 

1899 >>> np.ma.flatnotmasked_edges(a) 

1900 array([0, 9]) 

1901 

1902 >>> mask = (a < 3) | (a > 8) | (a == 5) 

1903 >>> a[mask] = np.ma.masked 

1904 >>> np.array(a[~a.mask]) 

1905 array([3, 4, 6, 7, 8]) 

1906 

1907 >>> np.ma.flatnotmasked_edges(a) 

1908 array([3, 8]) 

1909 

1910 >>> a[:] = np.ma.masked 

1911 >>> print(np.ma.flatnotmasked_edges(a)) 

1912 None 

1913 

1914 """ 

1915 m = getmask(a) 

1916 if m is nomask or not np.any(m): 

1917 return np.array([0, a.size - 1]) 

1918 unmasked = np.flatnonzero(~m) 

1919 if len(unmasked) > 0: 

1920 return unmasked[[0, -1]] 

1921 else: 

1922 return None 

1923 

1924 

1925def notmasked_edges(a, axis=None): 

1926 """ 

1927 Find the indices of the first and last unmasked values along an axis. 

1928 

1929 If all values are masked, return None. Otherwise, return a list 

1930 of two tuples, corresponding to the indices of the first and last 

1931 unmasked values respectively. 

1932 

1933 Parameters 

1934 ---------- 

1935 a : array_like 

1936 The input array. 

1937 axis : int, optional 

1938 Axis along which to perform the operation. 

1939 If None (default), applies to a flattened version of the array. 

1940 

1941 Returns 

1942 ------- 

1943 edges : ndarray or list 

1944 An array of start and end indexes if there are any masked data in 

1945 the array. If there are no masked data in the array, `edges` is a 

1946 list of the first and last index. 

1947 

1948 See Also 

1949 -------- 

1950 flatnotmasked_contiguous, flatnotmasked_edges, notmasked_contiguous 

1951 clump_masked, clump_unmasked 

1952 

1953 Examples 

1954 -------- 

1955 >>> import numpy as np 

1956 >>> a = np.arange(9).reshape((3, 3)) 

1957 >>> m = np.zeros_like(a) 

1958 >>> m[1:, 1:] = 1 

1959 

1960 >>> am = np.ma.array(a, mask=m) 

1961 >>> np.array(am[~am.mask]) 

1962 array([0, 1, 2, 3, 6]) 

1963 

1964 >>> np.ma.notmasked_edges(am) 

1965 array([0, 6]) 

1966 

1967 """ 

1968 a = asarray(a) 

1969 if axis is None or a.ndim == 1: 

1970 return flatnotmasked_edges(a) 

1971 m = getmaskarray(a) 

1972 idx = array(np.indices(a.shape), mask=np.asarray([m] * a.ndim)) 

1973 return [tuple(idx[i].min(axis).compressed() for i in range(a.ndim)), 

1974 tuple(idx[i].max(axis).compressed() for i in range(a.ndim)), ] 

1975 

1976 

1977def flatnotmasked_contiguous(a): 

1978 """ 

1979 Find contiguous unmasked data in a masked array. 

1980 

1981 Parameters 

1982 ---------- 

1983 a : array_like 

1984 The input array. 

1985 

1986 Returns 

1987 ------- 

1988 slice_list : list 

1989 A sorted sequence of `slice` objects (start index, end index). 

1990 

1991 See Also 

1992 -------- 

1993 flatnotmasked_edges, notmasked_contiguous, notmasked_edges 

1994 clump_masked, clump_unmasked 

1995 

1996 Notes 

1997 ----- 

1998 Only accepts 2-D arrays at most. 

1999 

2000 Examples 

2001 -------- 

2002 >>> import numpy as np 

2003 >>> a = np.ma.arange(10) 

2004 >>> np.ma.flatnotmasked_contiguous(a) 

2005 [slice(0, 10, None)] 

2006 

2007 >>> mask = (a < 3) | (a > 8) | (a == 5) 

2008 >>> a[mask] = np.ma.masked 

2009 >>> np.array(a[~a.mask]) 

2010 array([3, 4, 6, 7, 8]) 

2011 

2012 >>> np.ma.flatnotmasked_contiguous(a) 

2013 [slice(3, 5, None), slice(6, 9, None)] 

2014 >>> a[:] = np.ma.masked 

2015 >>> np.ma.flatnotmasked_contiguous(a) 

2016 [] 

2017 

2018 """ 

2019 m = getmask(a) 

2020 if m is nomask: 

2021 return [slice(0, a.size)] 

2022 i = 0 

2023 result = [] 

2024 for (k, g) in itertools.groupby(m.ravel()): 

2025 n = len(list(g)) 

2026 if not k: 

2027 result.append(slice(i, i + n)) 

2028 i += n 

2029 return result 

2030 

2031 

2032def notmasked_contiguous(a, axis=None): 

2033 """ 

2034 Find contiguous unmasked data in a masked array along the given axis. 

2035 

2036 Parameters 

2037 ---------- 

2038 a : array_like 

2039 The input array. 

2040 axis : int, optional 

2041 Axis along which to perform the operation. 

2042 If None (default), applies to a flattened version of the array, and this 

2043 is the same as `flatnotmasked_contiguous`. 

2044 

2045 Returns 

2046 ------- 

2047 endpoints : list 

2048 A list of slices (start and end indexes) of unmasked indexes 

2049 in the array. 

2050 

2051 If the input is 2d and axis is specified, the result is a list of lists. 

2052 

2053 See Also 

2054 -------- 

2055 flatnotmasked_edges, flatnotmasked_contiguous, notmasked_edges 

2056 clump_masked, clump_unmasked 

2057 

2058 Notes 

2059 ----- 

2060 Only accepts 2-D arrays at most. 

2061 

2062 Examples 

2063 -------- 

2064 >>> import numpy as np 

2065 >>> a = np.arange(12).reshape((3, 4)) 

2066 >>> mask = np.zeros_like(a) 

2067 >>> mask[1:, :-1] = 1; mask[0, 1] = 1; mask[-1, 0] = 0 

2068 >>> ma = np.ma.array(a, mask=mask) 

2069 >>> ma 

2070 masked_array( 

2071 data=[[0, --, 2, 3], 

2072 [--, --, --, 7], 

2073 [8, --, --, 11]], 

2074 mask=[[False, True, False, False], 

2075 [ True, True, True, False], 

2076 [False, True, True, False]], 

2077 fill_value=999999) 

2078 >>> np.array(ma[~ma.mask]) 

2079 array([ 0, 2, 3, 7, 8, 11]) 

2080 

2081 >>> np.ma.notmasked_contiguous(ma) 

2082 [slice(0, 1, None), slice(2, 4, None), slice(7, 9, None), slice(11, 12, None)] 

2083 

2084 >>> np.ma.notmasked_contiguous(ma, axis=0) 

2085 [[slice(0, 1, None), slice(2, 3, None)], [], [slice(0, 1, None)], [slice(0, 3, None)]] 

2086 

2087 >>> np.ma.notmasked_contiguous(ma, axis=1) 

2088 [[slice(0, 1, None), slice(2, 4, None)], [slice(3, 4, None)], [slice(0, 1, None), slice(3, 4, None)]] 

2089 

2090 """ # noqa: E501 

2091 a = asarray(a) 

2092 nd = a.ndim 

2093 if nd > 2: 

2094 raise NotImplementedError("Currently limited to at most 2D array.") 

2095 if axis is None or nd == 1: 

2096 return flatnotmasked_contiguous(a) 

2097 # 

2098 result = [] 

2099 # 

2100 other = (axis + 1) % 2 

2101 idx = [0, 0] 

2102 idx[axis] = slice(None, None) 

2103 # 

2104 for i in range(a.shape[other]): 

2105 idx[other] = i 

2106 result.append(flatnotmasked_contiguous(a[tuple(idx)])) 

2107 return result 

2108 

2109 

2110def _ezclump(mask): 

2111 """ 

2112 Finds the clumps (groups of data with the same values) for a 1D bool array. 

2113 

2114 Returns a series of slices. 

2115 """ 

2116 if mask.ndim > 1: 

2117 mask = mask.ravel() 

2118 idx = (mask[1:] ^ mask[:-1]).nonzero() 

2119 idx = idx[0] + 1 

2120 

2121 if mask[0]: 

2122 if len(idx) == 0: 

2123 return [slice(0, mask.size)] 

2124 

2125 r = [slice(0, idx[0])] 

2126 r.extend((slice(left, right) 

2127 for left, right in zip(idx[1:-1:2], idx[2::2]))) 

2128 else: 

2129 if len(idx) == 0: 

2130 return [] 

2131 

2132 r = [slice(left, right) for left, right in zip(idx[:-1:2], idx[1::2])] 

2133 

2134 if mask[-1]: 

2135 r.append(slice(idx[-1], mask.size)) 

2136 return r 

2137 

2138 

2139def clump_unmasked(a): 

2140 """ 

2141 Return list of slices corresponding to the unmasked clumps of a 1-D array. 

2142 (A "clump" is defined as a contiguous region of the array). 

2143 

2144 Parameters 

2145 ---------- 

2146 a : ndarray 

2147 A one-dimensional masked array. 

2148 

2149 Returns 

2150 ------- 

2151 slices : list of slice 

2152 The list of slices, one for each continuous region of unmasked 

2153 elements in `a`. 

2154 

2155 See Also 

2156 -------- 

2157 flatnotmasked_edges, flatnotmasked_contiguous, notmasked_edges 

2158 notmasked_contiguous, clump_masked 

2159 

2160 Examples 

2161 -------- 

2162 >>> import numpy as np 

2163 >>> a = np.ma.masked_array(np.arange(10)) 

2164 >>> a[[0, 1, 2, 6, 8, 9]] = np.ma.masked 

2165 >>> np.ma.clump_unmasked(a) 

2166 [slice(3, 6, None), slice(7, 8, None)] 

2167 

2168 """ 

2169 mask = getattr(a, '_mask', nomask) 

2170 if mask is nomask: 

2171 return [slice(0, a.size)] 

2172 return _ezclump(~mask) 

2173 

2174 

2175def clump_masked(a): 

2176 """ 

2177 Returns a list of slices corresponding to the masked clumps of a 1-D array. 

2178 (A "clump" is defined as a contiguous region of the array). 

2179 

2180 Parameters 

2181 ---------- 

2182 a : ndarray 

2183 A one-dimensional masked array. 

2184 

2185 Returns 

2186 ------- 

2187 slices : list of slice 

2188 The list of slices, one for each continuous region of masked elements 

2189 in `a`. 

2190 

2191 See Also 

2192 -------- 

2193 flatnotmasked_edges, flatnotmasked_contiguous, notmasked_edges 

2194 notmasked_contiguous, clump_unmasked 

2195 

2196 Examples 

2197 -------- 

2198 >>> import numpy as np 

2199 >>> a = np.ma.masked_array(np.arange(10)) 

2200 >>> a[[0, 1, 2, 6, 8, 9]] = np.ma.masked 

2201 >>> np.ma.clump_masked(a) 

2202 [slice(0, 3, None), slice(6, 7, None), slice(8, 10, None)] 

2203 

2204 """ 

2205 mask = ma.getmask(a) 

2206 if mask is nomask: 

2207 return [] 

2208 return _ezclump(mask) 

2209 

2210 

2211############################################################################### 

2212# Polynomial fit # 

2213############################################################################### 

2214 

2215 

2216def vander(x, n=None): 

2217 """ 

2218 Masked values in the input array result in rows of zeros. 

2219 

2220 """ 

2221 _vander = np.vander(x, n) 

2222 m = getmask(x) 

2223 if m is not nomask: 

2224 _vander[m] = 0 

2225 return _vander 

2226 

2227 

2228vander.__doc__ = ma.doc_note(np.vander.__doc__, vander.__doc__) 

2229 

2230 

2231def polyfit(x, y, deg, rcond=None, full=False, w=None, cov=False): 

2232 """ 

2233 Any masked values in x is propagated in y, and vice-versa. 

2234 

2235 """ 

2236 x = asarray(x) 

2237 y = asarray(y) 

2238 

2239 m = getmask(x) 

2240 if y.ndim == 1: 

2241 m = mask_or(m, getmask(y)) 

2242 elif y.ndim == 2: 

2243 my = getmask(mask_rows(y)) 

2244 if my is not nomask: 

2245 m = mask_or(m, my[:, 0]) 

2246 else: 

2247 raise TypeError("Expected a 1D or 2D array for y!") 

2248 

2249 if w is not None: 

2250 w = asarray(w) 

2251 if w.ndim != 1: 

2252 raise TypeError("expected a 1-d array for weights") 

2253 if w.shape[0] != y.shape[0]: 

2254 raise TypeError("expected w and y to have the same length") 

2255 m = mask_or(m, getmask(w)) 

2256 

2257 if m is not nomask: 

2258 not_m = ~m 

2259 if w is not None: 

2260 w = w[not_m] 

2261 return np.polyfit(x[not_m], y[not_m], deg, rcond, full, w, cov) 

2262 else: 

2263 return np.polyfit(x, y, deg, rcond, full, w, cov) 

2264 

2265 

2266polyfit.__doc__ = ma.doc_note(np.polyfit.__doc__, polyfit.__doc__)