Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.9/dist-packages/numpy/ma/extras.py: 16%

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

579 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:version: $Id: extras.py 3473 2007-10-29 15:18:13Z jarrod.millman $ 

9 

10""" 

11__all__ = [ 

12 'apply_along_axis', 'apply_over_axes', 'atleast_1d', 'atleast_2d', 

13 'atleast_3d', 'average', 'clump_masked', 'clump_unmasked', 'column_stack', 

14 'compress_cols', 'compress_nd', 'compress_rowcols', 'compress_rows', 

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

16 'flatnotmasked_contiguous', 'flatnotmasked_edges', 'hsplit', 'hstack', 

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

18 'masked_all', 'masked_all_like', 'median', 'mr_', 'ndenumerate', 

19 'notmasked_contiguous', 'notmasked_edges', 'polyfit', 'row_stack', 

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

21 ] 

22 

23import itertools 

24import warnings 

25 

26from . import core as ma 

27from .core import ( 

28 MaskedArray, MAError, add, array, asarray, concatenate, filled, count, 

29 getmask, getmaskarray, make_mask_descr, masked, masked_array, mask_or, 

30 nomask, ones, sort, zeros, getdata, get_masked_subclass, dot 

31 ) 

32 

33import numpy as np 

34from numpy import ndarray, array as nxarray 

35from numpy.core.multiarray import normalize_axis_index 

36from numpy.core.numeric import normalize_axis_tuple 

37from numpy.lib.function_base import _ureduce 

38from numpy.lib.index_tricks import AxisConcatenator 

39 

40 

41def issequence(seq): 

42 """ 

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

44 

45 """ 

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

47 

48 

49def count_masked(arr, axis=None): 

50 """ 

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

52 

53 Parameters 

54 ---------- 

55 arr : array_like 

56 An array with (possibly) masked elements. 

57 axis : int, optional 

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

59 version of the array is used. 

60 

61 Returns 

62 ------- 

63 count : int, ndarray 

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

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

66 

67 See Also 

68 -------- 

69 MaskedArray.count : Count non-masked elements. 

70 

71 Examples 

72 -------- 

73 >>> import numpy.ma as ma 

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

75 >>> a = ma.array(a) 

76 >>> a[1, 0] = ma.masked 

77 >>> a[1, 2] = ma.masked 

78 >>> a[2, 1] = ma.masked 

79 >>> a 

80 masked_array( 

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

82 [--, 4, --], 

83 [6, --, 8]], 

84 mask=[[False, False, False], 

85 [ True, False, True], 

86 [False, True, False]], 

87 fill_value=999999) 

88 >>> ma.count_masked(a) 

89 3 

90 

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

92 

93 >>> ma.count_masked(a, axis=0) 

94 array([1, 1, 1]) 

95 >>> ma.count_masked(a, axis=1) 

96 array([0, 2, 1]) 

97 

98 """ 

99 m = getmaskarray(arr) 

100 return m.sum(axis) 

101 

102 

103def masked_all(shape, dtype=float): 

104 """ 

105 Empty masked array with all elements masked. 

106 

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

108 data are masked. 

109 

110 Parameters 

111 ---------- 

112 shape : int or tuple of ints 

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

114 dtype : dtype, optional 

115 Data type of the output. 

116 

117 Returns 

118 ------- 

119 a : MaskedArray 

120 A masked array with all data masked. 

121 

122 See Also 

123 -------- 

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

125 

126 Examples 

127 -------- 

128 >>> import numpy.ma as ma 

129 >>> ma.masked_all((3, 3)) 

130 masked_array( 

131 data=[[--, --, --], 

132 [--, --, --], 

133 [--, --, --]], 

134 mask=[[ True, True, True], 

135 [ True, True, True], 

136 [ True, True, True]], 

137 fill_value=1e+20, 

138 dtype=float64) 

139 

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

141 

142 >>> a = ma.masked_all((3, 3)) 

143 >>> a.dtype 

144 dtype('float64') 

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

146 >>> a.dtype 

147 dtype('int32') 

148 

149 """ 

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

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

152 return a 

153 

154 

155def masked_all_like(arr): 

156 """ 

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

158 

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

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

161 

162 Parameters 

163 ---------- 

164 arr : ndarray 

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

166 

167 Returns 

168 ------- 

169 a : MaskedArray 

170 A masked array with all data masked. 

171 

172 Raises 

173 ------ 

174 AttributeError 

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

176 

177 See Also 

178 -------- 

179 masked_all : Empty masked array with all elements masked. 

180 

181 Examples 

182 -------- 

183 >>> import numpy.ma as ma 

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

185 >>> arr 

186 array([[0., 0., 0.], 

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

188 >>> ma.masked_all_like(arr) 

189 masked_array( 

190 data=[[--, --, --], 

191 [--, --, --]], 

192 mask=[[ True, True, True], 

193 [ True, True, True]], 

194 fill_value=1e+20, 

195 dtype=float32) 

196 

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

198 

199 >>> arr.dtype 

200 dtype('float32') 

201 >>> ma.masked_all_like(arr).dtype 

202 dtype('float32') 

203 

204 """ 

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

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

207 return a 

208 

209 

210#####-------------------------------------------------------------------------- 

211#---- --- Standard functions --- 

212#####-------------------------------------------------------------------------- 

213class _fromnxfunction: 

214 """ 

215 Defines a wrapper to adapt NumPy functions to masked arrays. 

216 

217 

218 An instance of `_fromnxfunction` can be called with the same parameters 

219 as the wrapped NumPy function. The docstring of `newfunc` is adapted from 

220 the wrapped function as well, see `getdoc`. 

221 

222 This class should not be used directly. Instead, one of its extensions that 

223 provides support for a specific type of input should be used. 

224 

225 Parameters 

226 ---------- 

227 funcname : str 

228 The name of the function to be adapted. The function should be 

229 in the NumPy namespace (i.e. ``np.funcname``). 

230 

231 """ 

232 

233 def __init__(self, funcname): 

234 self.__name__ = funcname 

235 self.__doc__ = self.getdoc() 

236 

237 def getdoc(self): 

238 """ 

239 Retrieve the docstring and signature from the function. 

240 

241 The ``__doc__`` attribute of the function is used as the docstring for 

242 the new masked array version of the function. A note on application 

243 of the function to the mask is appended. 

244 

245 Parameters 

246 ---------- 

247 None 

248 

249 """ 

250 npfunc = getattr(np, self.__name__, None) 

251 doc = getattr(npfunc, '__doc__', None) 

252 if doc: 

253 sig = self.__name__ + ma.get_object_signature(npfunc) 

254 doc = ma.doc_note(doc, "The function is applied to both the _data " 

255 "and the _mask, if any.") 

256 return '\n\n'.join((sig, doc)) 

257 return 

258 

259 def __call__(self, *args, **params): 

260 pass 

261 

262 

263class _fromnxfunction_single(_fromnxfunction): 

264 """ 

265 A version of `_fromnxfunction` that is called with a single array 

266 argument followed by auxiliary args that are passed verbatim for 

267 both the data and mask calls. 

268 """ 

269 def __call__(self, x, *args, **params): 

270 func = getattr(np, self.__name__) 

271 if isinstance(x, ndarray): 

272 _d = func(x.__array__(), *args, **params) 

273 _m = func(getmaskarray(x), *args, **params) 

274 return masked_array(_d, mask=_m) 

275 else: 

276 _d = func(np.asarray(x), *args, **params) 

277 _m = func(getmaskarray(x), *args, **params) 

278 return masked_array(_d, mask=_m) 

279 

280 

281class _fromnxfunction_seq(_fromnxfunction): 

282 """ 

283 A version of `_fromnxfunction` that is called with a single sequence 

284 of arrays followed by auxiliary args that are passed verbatim for 

285 both the data and mask calls. 

286 """ 

287 def __call__(self, x, *args, **params): 

288 func = getattr(np, self.__name__) 

289 _d = func(tuple([np.asarray(a) for a in x]), *args, **params) 

290 _m = func(tuple([getmaskarray(a) for a in x]), *args, **params) 

291 return masked_array(_d, mask=_m) 

292 

293 

294class _fromnxfunction_args(_fromnxfunction): 

295 """ 

296 A version of `_fromnxfunction` that is called with multiple array 

297 arguments. The first non-array-like input marks the beginning of the 

298 arguments that are passed verbatim for both the data and mask calls. 

299 Array arguments are processed independently and the results are 

300 returned in a list. If only one array is found, the return value is 

301 just the processed array instead of a list. 

302 """ 

303 def __call__(self, *args, **params): 

304 func = getattr(np, self.__name__) 

305 arrays = [] 

306 args = list(args) 

307 while len(args) > 0 and issequence(args[0]): 

308 arrays.append(args.pop(0)) 

309 res = [] 

310 for x in arrays: 

311 _d = func(np.asarray(x), *args, **params) 

312 _m = func(getmaskarray(x), *args, **params) 

313 res.append(masked_array(_d, mask=_m)) 

314 if len(arrays) == 1: 

315 return res[0] 

316 return res 

317 

318 

319class _fromnxfunction_allargs(_fromnxfunction): 

320 """ 

321 A version of `_fromnxfunction` that is called with multiple array 

322 arguments. Similar to `_fromnxfunction_args` except that all args 

323 are converted to arrays even if they are not so already. This makes 

324 it possible to process scalars as 1-D arrays. Only keyword arguments 

325 are passed through verbatim for the data and mask calls. Arrays 

326 arguments are processed independently and the results are returned 

327 in a list. If only one arg is present, the return value is just the 

328 processed array instead of a list. 

329 """ 

330 def __call__(self, *args, **params): 

331 func = getattr(np, self.__name__) 

332 res = [] 

333 for x in args: 

334 _d = func(np.asarray(x), **params) 

335 _m = func(getmaskarray(x), **params) 

336 res.append(masked_array(_d, mask=_m)) 

337 if len(args) == 1: 

338 return res[0] 

339 return res 

340 

341 

342atleast_1d = _fromnxfunction_allargs('atleast_1d') 

343atleast_2d = _fromnxfunction_allargs('atleast_2d') 

344atleast_3d = _fromnxfunction_allargs('atleast_3d') 

345 

346vstack = row_stack = _fromnxfunction_seq('vstack') 

347hstack = _fromnxfunction_seq('hstack') 

348column_stack = _fromnxfunction_seq('column_stack') 

349dstack = _fromnxfunction_seq('dstack') 

350stack = _fromnxfunction_seq('stack') 

351 

352hsplit = _fromnxfunction_single('hsplit') 

353 

354diagflat = _fromnxfunction_single('diagflat') 

355 

356 

357#####-------------------------------------------------------------------------- 

358#---- 

359#####-------------------------------------------------------------------------- 

360def flatten_inplace(seq): 

361 """Flatten a sequence in place.""" 

362 k = 0 

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

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

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

366 k += 1 

367 return seq 

368 

369 

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

371 """ 

372 (This docstring should be overwritten) 

373 """ 

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

375 nd = arr.ndim 

376 axis = normalize_axis_index(axis, nd) 

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

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

379 indlist = list(range(nd)) 

380 indlist.remove(axis) 

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

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

383 i.put(indlist, ind) 

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

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

386 asscalar = np.isscalar(res) 

387 if not asscalar: 

388 try: 

389 len(res) 

390 except TypeError: 

391 asscalar = True 

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

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

394 # just take the largest, to avoid some downcasting 

395 dtypes = [] 

396 if asscalar: 

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

398 outarr = zeros(outshape, object) 

399 outarr[tuple(ind)] = res 

400 Ntot = np.prod(outshape) 

401 k = 1 

402 while k < Ntot: 

403 # increment the index 

404 ind[-1] += 1 

405 n = -1 

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

407 ind[n - 1] += 1 

408 ind[n] = 0 

409 n -= 1 

410 i.put(indlist, ind) 

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

412 outarr[tuple(ind)] = res 

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

414 k += 1 

415 else: 

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

417 j = i.copy() 

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

419 j.put(indlist, ind) 

420 Ntot = np.prod(outshape) 

421 holdshape = outshape 

422 outshape = list(arr.shape) 

423 outshape[axis] = res.shape 

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

425 outshape = flatten_inplace(outshape) 

426 outarr = zeros(outshape, object) 

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

428 k = 1 

429 while k < Ntot: 

430 # increment the index 

431 ind[-1] += 1 

432 n = -1 

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

434 ind[n - 1] += 1 

435 ind[n] = 0 

436 n -= 1 

437 i.put(indlist, ind) 

438 j.put(indlist, ind) 

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

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

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

442 k += 1 

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

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

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

446 else: 

447 result = asarray(outarr, dtype=max_dtypes) 

448 result.fill_value = ma.default_fill_value(result) 

449 return result 

450apply_along_axis.__doc__ = np.apply_along_axis.__doc__ 

451 

452 

453def apply_over_axes(func, a, axes): 

454 """ 

455 (This docstring will be overwritten) 

456 """ 

457 val = asarray(a) 

458 N = a.ndim 

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

460 axes = (axes,) 

461 for axis in axes: 

462 if axis < 0: 

463 axis = N + axis 

464 args = (val, axis) 

465 res = func(*args) 

466 if res.ndim == val.ndim: 

467 val = res 

468 else: 

469 res = ma.expand_dims(res, axis) 

470 if res.ndim == val.ndim: 

471 val = res 

472 else: 

473 raise ValueError("function is not returning " 

474 "an array of the correct shape") 

475 return val 

476 

477 

478if apply_over_axes.__doc__ is not None: 

479 apply_over_axes.__doc__ = np.apply_over_axes.__doc__[ 

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

481 """ 

482 

483 Examples 

484 -------- 

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

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

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

488 >>> a 

489 masked_array( 

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

491 [--, --, --, --], 

492 [8, 9, 10, 11]], 

493 [[12, --, 14, 15], 

494 [--, --, --, --], 

495 [20, 21, 22, 23]]], 

496 mask=[[[False, True, False, False], 

497 [ True, True, True, True], 

498 [False, False, False, False]], 

499 [[False, True, False, False], 

500 [ True, True, True, True], 

501 [False, False, False, False]]], 

502 fill_value=999999) 

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

504 masked_array( 

505 data=[[[46], 

506 [--], 

507 [124]]], 

508 mask=[[[False], 

509 [ True], 

510 [False]]], 

511 fill_value=999999) 

512 

513 Tuple axis arguments to ufuncs are equivalent: 

514 

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

516 masked_array( 

517 data=[[[46], 

518 [--], 

519 [124]]], 

520 mask=[[[False], 

521 [ True], 

522 [False]]], 

523 fill_value=999999) 

524 """ 

525 

526 

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

528 keepdims=np._NoValue): 

529 """ 

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

531 

532 Parameters 

533 ---------- 

534 a : array_like 

535 Data to be averaged. 

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

537 axis : int, optional 

538 Axis along which to average `a`. If None, averaging is done over 

539 the flattened array. 

540 weights : array_like, optional 

541 The importance that each element has in the computation of the average. 

542 The weights array can either be 1-D (in which case its length must be 

543 the size of `a` along the given axis) or of the same shape as `a`. 

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

545 weight equal to one. The 1-D calculation is:: 

546 

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

548 

549 The only constraint on `weights` is that `sum(weights)` must not be 0. 

550 returned : bool, optional 

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

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

553 Default is False. 

554 keepdims : bool, optional 

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

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

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

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

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

560 

561 .. versionadded:: 1.23.0 

562 

563 Returns 

564 ------- 

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

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

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

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

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

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

571 `float64`. 

572 

573 Examples 

574 -------- 

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

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

577 1.25 

578 

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

580 >>> x 

581 masked_array( 

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

583 [2., 3.], 

584 [4., 5.]], 

585 mask=False, 

586 fill_value=1e+20) 

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

588 ... returned=True) 

589 >>> avg 

590 masked_array(data=[2.6666666666666665, 3.6666666666666665], 

591 mask=[False, False], 

592 fill_value=1e+20) 

593 

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

595 

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

597 masked_array( 

598 data=[[0.5], 

599 [2.5], 

600 [4.5]], 

601 mask=False, 

602 fill_value=1e+20) 

603 """ 

604 a = asarray(a) 

605 m = getmask(a) 

606 

607 # inspired by 'average' in numpy/lib/function_base.py 

608 

609 if keepdims is np._NoValue: 

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

611 keepdims_kw = {} 

612 else: 

613 keepdims_kw = {'keepdims': keepdims} 

614 

615 if weights is None: 

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

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

618 else: 

619 wgt = asarray(weights) 

620 

621 if issubclass(a.dtype.type, (np.integer, np.bool_)): 

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

623 else: 

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

625 

626 # Sanity checks 

627 if a.shape != wgt.shape: 

628 if axis is None: 

629 raise TypeError( 

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

631 "differ.") 

632 if wgt.ndim != 1: 

633 raise TypeError( 

634 "1D weights expected when shapes of a and weights differ.") 

635 if wgt.shape[0] != a.shape[axis]: 

636 raise ValueError( 

637 "Length of weights not compatible with specified axis.") 

638 

639 # setup wgt to broadcast along axis 

640 wgt = np.broadcast_to(wgt, (a.ndim-1)*(1,) + wgt.shape, subok=True) 

641 wgt = wgt.swapaxes(-1, axis) 

642 

643 if m is not nomask: 

644 wgt = wgt*(~a.mask) 

645 wgt.mask |= a.mask 

646 

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

648 avg = np.multiply(a, wgt, 

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

650 

651 if returned: 

652 if scl.shape != avg.shape: 

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

654 return avg, scl 

655 else: 

656 return avg 

657 

658 

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

660 """ 

661 Compute the median along the specified axis. 

662 

663 Returns the median of the array elements. 

664 

665 Parameters 

666 ---------- 

667 a : array_like 

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

669 axis : int, optional 

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

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

672 out : ndarray, optional 

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

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

675 but the type will be cast if necessary. 

676 overwrite_input : bool, optional 

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

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

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

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

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

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

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

684 keepdims : bool, optional 

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

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

687 the result will broadcast correctly against the input array. 

688 

689 .. versionadded:: 1.10.0 

690 

691 Returns 

692 ------- 

693 median : ndarray 

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

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

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

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

698 

699 See Also 

700 -------- 

701 mean 

702 

703 Notes 

704 ----- 

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

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

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

708 when ``N`` is even. 

709 

710 Examples 

711 -------- 

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

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

714 1.5 

715 

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

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

718 2.5 

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

720 masked_array(data=[2.0, 5.0], 

721 mask=[False, False], 

722 fill_value=1e+20) 

723 

724 """ 

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

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

727 out=out, overwrite_input=overwrite_input, 

728 keepdims=keepdims) 

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

730 return masked_array(m, copy=False) 

731 else: 

732 return m 

733 

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

735 overwrite_input=overwrite_input) 

736 

737 

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

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

740 # values behind the mask 

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

742 fill_value = np.inf 

743 else: 

744 fill_value = None 

745 if overwrite_input: 

746 if axis is None: 

747 asorted = a.ravel() 

748 asorted.sort(fill_value=fill_value) 

749 else: 

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

751 asorted = a 

752 else: 

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

754 

755 if axis is None: 

756 axis = 0 

757 else: 

758 axis = normalize_axis_index(axis, asorted.ndim) 

759 

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

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

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

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

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

765 indexer = tuple(indexer) 

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

767 

768 if asorted.ndim == 1: 

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

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

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

772 # avoid inf / x = masked 

773 s = mid.sum(out=out) 

774 if not odd: 

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

776 s = np.lib.utils._median_nancheck(asorted, s, axis) 

777 else: 

778 s = mid.mean(out=out) 

779 

780 # if result is masked either the input contained enough 

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

782 # masked 

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

784 return np.ma.minimum_fill_value(asorted) 

785 return s 

786 

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

788 h = counts // 2 

789 

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

791 odd = counts % 2 == 1 

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

793 

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

795 

796 # get low and high median 

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

798 

799 def replace_masked(s): 

800 # Replace masked entries with minimum_full_value unless it all values 

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

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

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

804 if np.ma.is_masked(s): 

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

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

807 s.mask[rep] = False 

808 

809 replace_masked(low_high) 

810 

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

812 # avoid inf / x = masked 

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

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

815 

816 s = np.lib.utils._median_nancheck(asorted, s, axis) 

817 else: 

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

819 

820 return s 

821 

822 

823def compress_nd(x, axis=None): 

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

825 

826 Parameters 

827 ---------- 

828 x : array_like, MaskedArray 

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

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

831 set to `nomask`. 

832 axis : tuple of ints or int, optional 

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

834 parameter. 

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

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

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

838 

839 Returns 

840 ------- 

841 compress_array : ndarray 

842 The compressed array. 

843 """ 

844 x = asarray(x) 

845 m = getmask(x) 

846 # Set axis to tuple of ints 

847 if axis is None: 

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

849 else: 

850 axis = normalize_axis_tuple(axis, x.ndim) 

851 

852 # Nothing is masked: return x 

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

854 return x._data 

855 # All is masked: return empty 

856 if m.all(): 

857 return nxarray([]) 

858 # Filter elements through boolean indexing 

859 data = x._data 

860 for ax in axis: 

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

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

863 return data 

864 

865 

866def compress_rowcols(x, axis=None): 

867 """ 

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

869 masked values. 

870 

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

872 

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

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

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

876 

877 Parameters 

878 ---------- 

879 x : array_like, MaskedArray 

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

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

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

883 axis : int, optional 

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

885 

886 Returns 

887 ------- 

888 compressed_array : ndarray 

889 The compressed array. 

890 

891 Examples 

892 -------- 

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

894 ... [1, 0, 0], 

895 ... [0, 0, 0]]) 

896 >>> x 

897 masked_array( 

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

899 [--, 4, 5], 

900 [6, 7, 8]], 

901 mask=[[ True, False, False], 

902 [ True, False, False], 

903 [False, False, False]], 

904 fill_value=999999) 

905 

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

907 array([[7, 8]]) 

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

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

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

911 array([[1, 2], 

912 [4, 5], 

913 [7, 8]]) 

914 

915 """ 

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

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

918 return compress_nd(x, axis=axis) 

919 

920 

921def compress_rows(a): 

922 """ 

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

924 

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

926 `compress_rowcols` for details. 

927 

928 See Also 

929 -------- 

930 compress_rowcols 

931 

932 """ 

933 a = asarray(a) 

934 if a.ndim != 2: 

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

936 return compress_rowcols(a, 0) 

937 

938 

939def compress_cols(a): 

940 """ 

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

942 

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

944 `compress_rowcols` for details. 

945 

946 See Also 

947 -------- 

948 compress_rowcols 

949 

950 """ 

951 a = asarray(a) 

952 if a.ndim != 2: 

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

954 return compress_rowcols(a, 1) 

955 

956 

957def mask_rowcols(a, axis=None): 

958 """ 

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

960 

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

962 masked values. The masking behavior is selected using the 

963 `axis` parameter. 

964 

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

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

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

968 

969 Parameters 

970 ---------- 

971 a : array_like, MaskedArray 

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

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

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

975 axis : int, optional 

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

977 flattened version of the array. 

978 

979 Returns 

980 ------- 

981 a : MaskedArray 

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

983 of the `axis` parameter. 

984 

985 Raises 

986 ------ 

987 NotImplementedError 

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

989 

990 See Also 

991 -------- 

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

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

994 masked_where : Mask where a condition is met. 

995 

996 Notes 

997 ----- 

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

999 

1000 Examples 

1001 -------- 

1002 >>> import numpy.ma as ma 

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

1004 >>> a[1, 1] = 1 

1005 >>> a 

1006 array([[0, 0, 0], 

1007 [0, 1, 0], 

1008 [0, 0, 0]]) 

1009 >>> a = ma.masked_equal(a, 1) 

1010 >>> a 

1011 masked_array( 

1012 data=[[0, 0, 0], 

1013 [0, --, 0], 

1014 [0, 0, 0]], 

1015 mask=[[False, False, False], 

1016 [False, True, False], 

1017 [False, False, False]], 

1018 fill_value=1) 

1019 >>> ma.mask_rowcols(a) 

1020 masked_array( 

1021 data=[[0, --, 0], 

1022 [--, --, --], 

1023 [0, --, 0]], 

1024 mask=[[False, True, False], 

1025 [ True, True, True], 

1026 [False, True, False]], 

1027 fill_value=1) 

1028 

1029 """ 

1030 a = array(a, subok=False) 

1031 if a.ndim != 2: 

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

1033 m = getmask(a) 

1034 # Nothing is masked: return a 

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

1036 return a 

1037 maskedval = m.nonzero() 

1038 a._mask = a._mask.copy() 

1039 if not axis: 

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

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

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

1043 return a 

1044 

1045 

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

1047 """ 

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

1049 

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

1051 

1052 See Also 

1053 -------- 

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

1055 masked_where : Mask where a condition is met. 

1056 

1057 Examples 

1058 -------- 

1059 >>> import numpy.ma as ma 

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

1061 >>> a[1, 1] = 1 

1062 >>> a 

1063 array([[0, 0, 0], 

1064 [0, 1, 0], 

1065 [0, 0, 0]]) 

1066 >>> a = ma.masked_equal(a, 1) 

1067 >>> a 

1068 masked_array( 

1069 data=[[0, 0, 0], 

1070 [0, --, 0], 

1071 [0, 0, 0]], 

1072 mask=[[False, False, False], 

1073 [False, True, False], 

1074 [False, False, False]], 

1075 fill_value=1) 

1076 

1077 >>> ma.mask_rows(a) 

1078 masked_array( 

1079 data=[[0, 0, 0], 

1080 [--, --, --], 

1081 [0, 0, 0]], 

1082 mask=[[False, False, False], 

1083 [ True, True, True], 

1084 [False, False, False]], 

1085 fill_value=1) 

1086 

1087 """ 

1088 if axis is not np._NoValue: 

1089 # remove the axis argument when this deprecation expires 

1090 # NumPy 1.18.0, 2019-11-28 

1091 warnings.warn( 

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

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

1094 return mask_rowcols(a, 0) 

1095 

1096 

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

1098 """ 

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

1100 

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

1102 

1103 See Also 

1104 -------- 

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

1106 masked_where : Mask where a condition is met. 

1107 

1108 Examples 

1109 -------- 

1110 >>> import numpy.ma as ma 

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

1112 >>> a[1, 1] = 1 

1113 >>> a 

1114 array([[0, 0, 0], 

1115 [0, 1, 0], 

1116 [0, 0, 0]]) 

1117 >>> a = ma.masked_equal(a, 1) 

1118 >>> a 

1119 masked_array( 

1120 data=[[0, 0, 0], 

1121 [0, --, 0], 

1122 [0, 0, 0]], 

1123 mask=[[False, False, False], 

1124 [False, True, False], 

1125 [False, False, False]], 

1126 fill_value=1) 

1127 >>> ma.mask_cols(a) 

1128 masked_array( 

1129 data=[[0, --, 0], 

1130 [0, --, 0], 

1131 [0, --, 0]], 

1132 mask=[[False, True, False], 

1133 [False, True, False], 

1134 [False, True, False]], 

1135 fill_value=1) 

1136 

1137 """ 

1138 if axis is not np._NoValue: 

1139 # remove the axis argument when this deprecation expires 

1140 # NumPy 1.18.0, 2019-11-28 

1141 warnings.warn( 

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

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

1144 return mask_rowcols(a, 1) 

1145 

1146 

1147#####-------------------------------------------------------------------------- 

1148#---- --- arraysetops --- 

1149#####-------------------------------------------------------------------------- 

1150 

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

1152 """ 

1153 Compute the differences between consecutive elements of an array. 

1154 

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

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

1157 

1158 See Also 

1159 -------- 

1160 numpy.ediff1d : Equivalent function for ndarrays. 

1161 

1162 """ 

1163 arr = ma.asanyarray(arr).flat 

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

1165 arrays = [ed] 

1166 # 

1167 if to_begin is not None: 

1168 arrays.insert(0, to_begin) 

1169 if to_end is not None: 

1170 arrays.append(to_end) 

1171 # 

1172 if len(arrays) != 1: 

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

1174 # case where neither to_begin or to_end was given. 

1175 ed = hstack(arrays) 

1176 # 

1177 return ed 

1178 

1179 

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

1181 """ 

1182 Finds the unique elements of an array. 

1183 

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

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

1186 

1187 See Also 

1188 -------- 

1189 numpy.unique : Equivalent function for ndarrays. 

1190 

1191 Examples 

1192 -------- 

1193 >>> import numpy.ma as ma 

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

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

1196 >>> masked_a = ma.masked_array(a, mask) 

1197 >>> masked_a 

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

1199 mask=[False, False, True, False, False], 

1200 fill_value=999999) 

1201 >>> ma.unique(masked_a) 

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

1203 mask=[False, False, False, True], 

1204 fill_value=999999) 

1205 >>> ma.unique(masked_a, return_index=True) 

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

1207 mask=[False, False, False, True], 

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

1209 >>> ma.unique(masked_a, return_inverse=True) 

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

1211 mask=[False, False, False, True], 

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

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

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

1215 mask=[False, False, False, True], 

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

1217 """ 

1218 output = np.unique(ar1, 

1219 return_index=return_index, 

1220 return_inverse=return_inverse) 

1221 if isinstance(output, tuple): 

1222 output = list(output) 

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

1224 output = tuple(output) 

1225 else: 

1226 output = output.view(MaskedArray) 

1227 return output 

1228 

1229 

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

1231 """ 

1232 Returns the unique elements common to both arrays. 

1233 

1234 Masked values are considered equal one to the other. 

1235 The output is always a masked array. 

1236 

1237 See `numpy.intersect1d` for more details. 

1238 

1239 See Also 

1240 -------- 

1241 numpy.intersect1d : Equivalent function for ndarrays. 

1242 

1243 Examples 

1244 -------- 

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

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

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

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

1249 mask=[False, False, True], 

1250 fill_value=999999) 

1251 

1252 """ 

1253 if assume_unique: 

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

1255 else: 

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

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

1258 aux.sort() 

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

1260 

1261 

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

1263 """ 

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

1265 

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

1267 

1268 See Also 

1269 -------- 

1270 numpy.setxor1d : Equivalent function for ndarrays. 

1271 

1272 """ 

1273 if not assume_unique: 

1274 ar1 = unique(ar1) 

1275 ar2 = unique(ar2) 

1276 

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

1278 if aux.size == 0: 

1279 return aux 

1280 aux.sort() 

1281 auxf = aux.filled() 

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

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

1284# flag2 = ediff1d( flag ) == 0 

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

1286 return aux[flag2] 

1287 

1288 

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

1290 """ 

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

1292 array. 

1293 

1294 The output is always a masked array. See `numpy.in1d` for more details. 

1295 

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

1297 

1298 See Also 

1299 -------- 

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

1301 numpy.in1d : Equivalent function for ndarrays. 

1302 

1303 Notes 

1304 ----- 

1305 .. versionadded:: 1.4.0 

1306 

1307 """ 

1308 if not assume_unique: 

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

1310 ar2 = unique(ar2) 

1311 

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

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

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

1315 # the values from the second array. 

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

1317 sar = ar[order] 

1318 if invert: 

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

1320 else: 

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

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

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

1324 

1325 if assume_unique: 

1326 return flag[indx] 

1327 else: 

1328 return flag[indx][rev_idx] 

1329 

1330 

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

1332 """ 

1333 Calculates `element in test_elements`, broadcasting over 

1334 `element` only. 

1335 

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

1337 See `numpy.isin` for more details. 

1338 

1339 See Also 

1340 -------- 

1341 in1d : Flattened version of this function. 

1342 numpy.isin : Equivalent function for ndarrays. 

1343 

1344 Notes 

1345 ----- 

1346 .. versionadded:: 1.13.0 

1347 

1348 """ 

1349 element = ma.asarray(element) 

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

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

1352 

1353 

1354def union1d(ar1, ar2): 

1355 """ 

1356 Union of two arrays. 

1357 

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

1359 

1360 See Also 

1361 -------- 

1362 numpy.union1d : Equivalent function for ndarrays. 

1363 

1364 """ 

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

1366 

1367 

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

1369 """ 

1370 Set difference of 1D arrays with unique elements. 

1371 

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

1373 details. 

1374 

1375 See Also 

1376 -------- 

1377 numpy.setdiff1d : Equivalent function for ndarrays. 

1378 

1379 Examples 

1380 -------- 

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

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

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

1384 mask=[False, True], 

1385 fill_value=999999) 

1386 

1387 """ 

1388 if assume_unique: 

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

1390 else: 

1391 ar1 = unique(ar1) 

1392 ar2 = unique(ar2) 

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

1394 

1395 

1396############################################################################### 

1397# Covariance # 

1398############################################################################### 

1399 

1400 

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

1402 """ 

1403 Private function for the computation of covariance and correlation 

1404 coefficients. 

1405 

1406 """ 

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

1408 xmask = ma.getmaskarray(x) 

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

1410 if not allow_masked and xmask.any(): 

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

1412 # 

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

1414 rowvar = True 

1415 # Make sure that rowvar is either 0 or 1 

1416 rowvar = int(bool(rowvar)) 

1417 axis = 1 - rowvar 

1418 if rowvar: 

1419 tup = (slice(None), None) 

1420 else: 

1421 tup = (None, slice(None)) 

1422 # 

1423 if y is None: 

1424 xnotmask = np.logical_not(xmask).astype(int) 

1425 else: 

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

1427 ymask = ma.getmaskarray(y) 

1428 if not allow_masked and ymask.any(): 

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

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

1431 if y.shape == x.shape: 

1432 # Define some common mask 

1433 common_mask = np.logical_or(xmask, ymask) 

1434 if common_mask is not nomask: 

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

1436 x._sharedmask = False 

1437 y._sharedmask = False 

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

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

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

1441 return (x, xnotmask, rowvar) 

1442 

1443 

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

1445 """ 

1446 Estimate the covariance matrix. 

1447 

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

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

1450 

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

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

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

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

1455 missing in either of the input arrays. 

1456 

1457 Parameters 

1458 ---------- 

1459 x : array_like 

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

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

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

1463 y : array_like, optional 

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

1465 shape as `x`. 

1466 rowvar : bool, optional 

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

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

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

1470 contain observations. 

1471 bias : bool, optional 

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

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

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

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

1476 allow_masked : bool, optional 

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

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

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

1480 ddof : {None, int}, optional 

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

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

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

1484 

1485 .. versionadded:: 1.5 

1486 

1487 Raises 

1488 ------ 

1489 ValueError 

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

1491 

1492 See Also 

1493 -------- 

1494 numpy.cov 

1495 

1496 """ 

1497 # Check inputs 

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

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

1500 # Set up ddof 

1501 if ddof is None: 

1502 if bias: 

1503 ddof = 0 

1504 else: 

1505 ddof = 1 

1506 

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

1508 if not rowvar: 

1509 fact = np.dot(xnotmask.T, xnotmask) * 1. - ddof 

1510 result = (dot(x.T, x.conj(), strict=False) / fact).squeeze() 

1511 else: 

1512 fact = np.dot(xnotmask, xnotmask.T) * 1. - ddof 

1513 result = (dot(x, x.T.conj(), strict=False) / fact).squeeze() 

1514 return result 

1515 

1516 

1517def corrcoef(x, y=None, rowvar=True, bias=np._NoValue, allow_masked=True, 

1518 ddof=np._NoValue): 

1519 """ 

1520 Return Pearson product-moment correlation coefficients. 

1521 

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

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

1524 

1525 Parameters 

1526 ---------- 

1527 x : array_like 

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

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

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

1531 y : array_like, optional 

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

1533 shape as `x`. 

1534 rowvar : bool, optional 

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

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

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

1538 contain observations. 

1539 bias : _NoValue, optional 

1540 Has no effect, do not use. 

1541 

1542 .. deprecated:: 1.10.0 

1543 allow_masked : bool, optional 

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

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

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

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

1548 ddof : _NoValue, optional 

1549 Has no effect, do not use. 

1550 

1551 .. deprecated:: 1.10.0 

1552 

1553 See Also 

1554 -------- 

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

1556 cov : Estimate the covariance matrix. 

1557 

1558 Notes 

1559 ----- 

1560 This function accepts but discards arguments `bias` and `ddof`. This is 

1561 for backwards compatibility with previous versions of this function. These 

1562 arguments had no effect on the return values of the function and can be 

1563 safely ignored in this and previous versions of numpy. 

1564 """ 

1565 msg = 'bias and ddof have no effect and are deprecated' 

1566 if bias is not np._NoValue or ddof is not np._NoValue: 

1567 # 2015-03-15, 1.10 

1568 warnings.warn(msg, DeprecationWarning, stacklevel=2) 

1569 # Get the data 

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

1571 # Compute the covariance matrix 

1572 if not rowvar: 

1573 fact = np.dot(xnotmask.T, xnotmask) * 1. 

1574 c = (dot(x.T, x.conj(), strict=False) / fact).squeeze() 

1575 else: 

1576 fact = np.dot(xnotmask, xnotmask.T) * 1. 

1577 c = (dot(x, x.T.conj(), strict=False) / fact).squeeze() 

1578 # Check whether we have a scalar 

1579 try: 

1580 diag = ma.diagonal(c) 

1581 except ValueError: 

1582 return 1 

1583 # 

1584 if xnotmask.all(): 

1585 _denom = ma.sqrt(ma.multiply.outer(diag, diag)) 

1586 else: 

1587 _denom = diagflat(diag) 

1588 _denom._sharedmask = False # We know return is always a copy 

1589 n = x.shape[1 - rowvar] 

1590 if rowvar: 

1591 for i in range(n - 1): 

1592 for j in range(i + 1, n): 

1593 _x = mask_cols(vstack((x[i], x[j]))).var(axis=1) 

1594 _denom[i, j] = _denom[j, i] = ma.sqrt(ma.multiply.reduce(_x)) 

1595 else: 

1596 for i in range(n - 1): 

1597 for j in range(i + 1, n): 

1598 _x = mask_cols( 

1599 vstack((x[:, i], x[:, j]))).var(axis=1) 

1600 _denom[i, j] = _denom[j, i] = ma.sqrt(ma.multiply.reduce(_x)) 

1601 return c / _denom 

1602 

1603#####-------------------------------------------------------------------------- 

1604#---- --- Concatenation helpers --- 

1605#####-------------------------------------------------------------------------- 

1606 

1607class MAxisConcatenator(AxisConcatenator): 

1608 """ 

1609 Translate slice objects to concatenation along an axis. 

1610 

1611 For documentation on usage, see `mr_class`. 

1612 

1613 See Also 

1614 -------- 

1615 mr_class 

1616 

1617 """ 

1618 concatenate = staticmethod(concatenate) 

1619 

1620 @classmethod 

1621 def makemat(cls, arr): 

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

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

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

1625 # with the .view) 

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

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

1628 

1629 def __getitem__(self, key): 

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

1631 if isinstance(key, str): 

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

1633 

1634 return super().__getitem__(key) 

1635 

1636 

1637class mr_class(MAxisConcatenator): 

1638 """ 

1639 Translate slice objects to concatenation along the first axis. 

1640 

1641 This is the masked array version of `lib.index_tricks.RClass`. 

1642 

1643 See Also 

1644 -------- 

1645 lib.index_tricks.RClass 

1646 

1647 Examples 

1648 -------- 

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

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

1651 mask=False, 

1652 fill_value=999999) 

1653 

1654 """ 

1655 def __init__(self): 

1656 MAxisConcatenator.__init__(self, 0) 

1657 

1658mr_ = mr_class() 

1659 

1660 

1661#####-------------------------------------------------------------------------- 

1662#---- Find unmasked data --- 

1663#####-------------------------------------------------------------------------- 

1664 

1665def ndenumerate(a, compressed=True): 

1666 """ 

1667 Multidimensional index iterator. 

1668 

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

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

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

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

1673 value of the underlying data array. 

1674 

1675 Notes 

1676 ----- 

1677 .. versionadded:: 1.23.0 

1678 

1679 Parameters 

1680 ---------- 

1681 a : array_like 

1682 An array with (possibly) masked elements. 

1683 compressed : bool, optional 

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

1685 

1686 See Also 

1687 -------- 

1688 numpy.ndenumerate : Equivalent function ignoring any mask. 

1689 

1690 Examples 

1691 -------- 

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

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

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

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

1696 >>> a 

1697 masked_array( 

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

1699 [--, 4, --], 

1700 [6, --, 8]], 

1701 mask=[[False, False, False], 

1702 [ True, False, True], 

1703 [False, True, False]], 

1704 fill_value=999999) 

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

1706 ... print(index, x) 

1707 (0, 0) 0 

1708 (0, 1) 1 

1709 (0, 2) 2 

1710 (1, 1) 4 

1711 (2, 0) 6 

1712 (2, 2) 8 

1713 

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

1715 ... print(index, x) 

1716 (0, 0) 0 

1717 (0, 1) 1 

1718 (0, 2) 2 

1719 (1, 0) -- 

1720 (1, 1) 4 

1721 (1, 2) -- 

1722 (2, 0) 6 

1723 (2, 1) -- 

1724 (2, 2) 8 

1725 """ 

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

1727 if not mask: 

1728 yield it 

1729 elif not compressed: 

1730 yield it[0], masked 

1731 

1732 

1733def flatnotmasked_edges(a): 

1734 """ 

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

1736 

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

1738 

1739 Parameters 

1740 ---------- 

1741 a : array_like 

1742 Input 1-D `MaskedArray` 

1743 

1744 Returns 

1745 ------- 

1746 edges : ndarray or None 

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

1748 Returns None if all values are masked. 

1749 

1750 See Also 

1751 -------- 

1752 flatnotmasked_contiguous, notmasked_contiguous, notmasked_edges 

1753 clump_masked, clump_unmasked 

1754 

1755 Notes 

1756 ----- 

1757 Only accepts 1-D arrays. 

1758 

1759 Examples 

1760 -------- 

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

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

1763 array([0, 9]) 

1764 

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

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

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

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

1769 

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

1771 array([3, 8]) 

1772 

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

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

1775 None 

1776 

1777 """ 

1778 m = getmask(a) 

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

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

1781 unmasked = np.flatnonzero(~m) 

1782 if len(unmasked) > 0: 

1783 return unmasked[[0, -1]] 

1784 else: 

1785 return None 

1786 

1787 

1788def notmasked_edges(a, axis=None): 

1789 """ 

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

1791 

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

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

1794 unmasked values respectively. 

1795 

1796 Parameters 

1797 ---------- 

1798 a : array_like 

1799 The input array. 

1800 axis : int, optional 

1801 Axis along which to perform the operation. 

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

1803 

1804 Returns 

1805 ------- 

1806 edges : ndarray or list 

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

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

1809 list of the first and last index. 

1810 

1811 See Also 

1812 -------- 

1813 flatnotmasked_contiguous, flatnotmasked_edges, notmasked_contiguous 

1814 clump_masked, clump_unmasked 

1815 

1816 Examples 

1817 -------- 

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

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

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

1821 

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

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

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

1825 

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

1827 array([0, 6]) 

1828 

1829 """ 

1830 a = asarray(a) 

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

1832 return flatnotmasked_edges(a) 

1833 m = getmaskarray(a) 

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

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

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

1837 

1838 

1839def flatnotmasked_contiguous(a): 

1840 """ 

1841 Find contiguous unmasked data in a masked array. 

1842 

1843 Parameters 

1844 ---------- 

1845 a : array_like 

1846 The input array. 

1847 

1848 Returns 

1849 ------- 

1850 slice_list : list 

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

1852 

1853 .. versionchanged:: 1.15.0 

1854 Now returns an empty list instead of None for a fully masked array 

1855 

1856 See Also 

1857 -------- 

1858 flatnotmasked_edges, notmasked_contiguous, notmasked_edges 

1859 clump_masked, clump_unmasked 

1860 

1861 Notes 

1862 ----- 

1863 Only accepts 2-D arrays at most. 

1864 

1865 Examples 

1866 -------- 

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

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

1869 [slice(0, 10, None)] 

1870 

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

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

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

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

1875 

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

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

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

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

1880 [] 

1881 

1882 """ 

1883 m = getmask(a) 

1884 if m is nomask: 

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

1886 i = 0 

1887 result = [] 

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

1889 n = len(list(g)) 

1890 if not k: 

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

1892 i += n 

1893 return result 

1894 

1895 

1896def notmasked_contiguous(a, axis=None): 

1897 """ 

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

1899 

1900 Parameters 

1901 ---------- 

1902 a : array_like 

1903 The input array. 

1904 axis : int, optional 

1905 Axis along which to perform the operation. 

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

1907 is the same as `flatnotmasked_contiguous`. 

1908 

1909 Returns 

1910 ------- 

1911 endpoints : list 

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

1913 in the array. 

1914 

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

1916 

1917 See Also 

1918 -------- 

1919 flatnotmasked_edges, flatnotmasked_contiguous, notmasked_edges 

1920 clump_masked, clump_unmasked 

1921 

1922 Notes 

1923 ----- 

1924 Only accepts 2-D arrays at most. 

1925 

1926 Examples 

1927 -------- 

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

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

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

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

1932 >>> ma 

1933 masked_array( 

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

1935 [--, --, --, 7], 

1936 [8, --, --, 11]], 

1937 mask=[[False, True, False, False], 

1938 [ True, True, True, False], 

1939 [False, True, True, False]], 

1940 fill_value=999999) 

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

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

1943 

1944 >>> np.ma.notmasked_contiguous(ma) 

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

1946 

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

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

1949 

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

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

1952 

1953 """ 

1954 a = asarray(a) 

1955 nd = a.ndim 

1956 if nd > 2: 

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

1958 if axis is None or nd == 1: 

1959 return flatnotmasked_contiguous(a) 

1960 # 

1961 result = [] 

1962 # 

1963 other = (axis + 1) % 2 

1964 idx = [0, 0] 

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

1966 # 

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

1968 idx[other] = i 

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

1970 return result 

1971 

1972 

1973def _ezclump(mask): 

1974 """ 

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

1976 

1977 Returns a series of slices. 

1978 """ 

1979 if mask.ndim > 1: 

1980 mask = mask.ravel() 

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

1982 idx = idx[0] + 1 

1983 

1984 if mask[0]: 

1985 if len(idx) == 0: 

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

1987 

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

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

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

1991 else: 

1992 if len(idx) == 0: 

1993 return [] 

1994 

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

1996 

1997 if mask[-1]: 

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

1999 return r 

2000 

2001 

2002def clump_unmasked(a): 

2003 """ 

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

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

2006 

2007 Parameters 

2008 ---------- 

2009 a : ndarray 

2010 A one-dimensional masked array. 

2011 

2012 Returns 

2013 ------- 

2014 slices : list of slice 

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

2016 elements in `a`. 

2017 

2018 Notes 

2019 ----- 

2020 .. versionadded:: 1.4.0 

2021 

2022 See Also 

2023 -------- 

2024 flatnotmasked_edges, flatnotmasked_contiguous, notmasked_edges 

2025 notmasked_contiguous, clump_masked 

2026 

2027 Examples 

2028 -------- 

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

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

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

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

2033 

2034 """ 

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

2036 if mask is nomask: 

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

2038 return _ezclump(~mask) 

2039 

2040 

2041def clump_masked(a): 

2042 """ 

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

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

2045 

2046 Parameters 

2047 ---------- 

2048 a : ndarray 

2049 A one-dimensional masked array. 

2050 

2051 Returns 

2052 ------- 

2053 slices : list of slice 

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

2055 in `a`. 

2056 

2057 Notes 

2058 ----- 

2059 .. versionadded:: 1.4.0 

2060 

2061 See Also 

2062 -------- 

2063 flatnotmasked_edges, flatnotmasked_contiguous, notmasked_edges 

2064 notmasked_contiguous, clump_unmasked 

2065 

2066 Examples 

2067 -------- 

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

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

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

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

2072 

2073 """ 

2074 mask = ma.getmask(a) 

2075 if mask is nomask: 

2076 return [] 

2077 return _ezclump(mask) 

2078 

2079 

2080############################################################################### 

2081# Polynomial fit # 

2082############################################################################### 

2083 

2084 

2085def vander(x, n=None): 

2086 """ 

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

2088 

2089 """ 

2090 _vander = np.vander(x, n) 

2091 m = getmask(x) 

2092 if m is not nomask: 

2093 _vander[m] = 0 

2094 return _vander 

2095 

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

2097 

2098 

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

2100 """ 

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

2102 

2103 """ 

2104 x = asarray(x) 

2105 y = asarray(y) 

2106 

2107 m = getmask(x) 

2108 if y.ndim == 1: 

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

2110 elif y.ndim == 2: 

2111 my = getmask(mask_rows(y)) 

2112 if my is not nomask: 

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

2114 else: 

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

2116 

2117 if w is not None: 

2118 w = asarray(w) 

2119 if w.ndim != 1: 

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

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

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

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

2124 

2125 if m is not nomask: 

2126 not_m = ~m 

2127 if w is not None: 

2128 w = w[not_m] 

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

2130 else: 

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

2132 

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