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

568 statements  

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

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 mask_rowcols 

32 ) 

33 

34import numpy as np 

35from numpy import ndarray, array as nxarray 

36from numpy.core.multiarray import normalize_axis_index 

37from numpy.core.numeric import normalize_axis_tuple 

38from numpy.lib.function_base import _ureduce 

39from numpy.lib.index_tricks import AxisConcatenator 

40 

41 

42def issequence(seq): 

43 """ 

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

45 

46 """ 

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

48 

49 

50def count_masked(arr, axis=None): 

51 """ 

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

53 

54 Parameters 

55 ---------- 

56 arr : array_like 

57 An array with (possibly) masked elements. 

58 axis : int, optional 

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

60 version of the array is used. 

61 

62 Returns 

63 ------- 

64 count : int, ndarray 

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

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

67 

68 See Also 

69 -------- 

70 MaskedArray.count : Count non-masked elements. 

71 

72 Examples 

73 -------- 

74 >>> import numpy.ma as ma 

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

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

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

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

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

80 >>> a 

81 masked_array( 

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

83 [--, 4, --], 

84 [6, --, 8]], 

85 mask=[[False, False, False], 

86 [ True, False, True], 

87 [False, True, False]], 

88 fill_value=999999) 

89 >>> ma.count_masked(a) 

90 3 

91 

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

93 

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

95 array([1, 1, 1]) 

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

97 array([0, 2, 1]) 

98 

99 """ 

100 m = getmaskarray(arr) 

101 return m.sum(axis) 

102 

103 

104def masked_all(shape, dtype=float): 

105 """ 

106 Empty masked array with all elements masked. 

107 

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

109 data are masked. 

110 

111 Parameters 

112 ---------- 

113 shape : int or tuple of ints 

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

115 dtype : dtype, optional 

116 Data type of the output. 

117 

118 Returns 

119 ------- 

120 a : MaskedArray 

121 A masked array with all data masked. 

122 

123 See Also 

124 -------- 

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

126 

127 Examples 

128 -------- 

129 >>> import numpy.ma as ma 

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

131 masked_array( 

132 data=[[--, --, --], 

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

134 [--, --, --]], 

135 mask=[[ True, True, True], 

136 [ True, True, True], 

137 [ True, True, True]], 

138 fill_value=1e+20, 

139 dtype=float64) 

140 

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

142 

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

144 >>> a.dtype 

145 dtype('float64') 

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

147 >>> a.dtype 

148 dtype('int32') 

149 

150 """ 

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

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

153 return a 

154 

155 

156def masked_all_like(arr): 

157 """ 

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

159 

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

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

162 

163 Parameters 

164 ---------- 

165 arr : ndarray 

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

167 

168 Returns 

169 ------- 

170 a : MaskedArray 

171 A masked array with all data masked. 

172 

173 Raises 

174 ------ 

175 AttributeError 

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

177 

178 See Also 

179 -------- 

180 masked_all : Empty masked array with all elements masked. 

181 

182 Examples 

183 -------- 

184 >>> import numpy.ma as ma 

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

186 >>> arr 

187 array([[0., 0., 0.], 

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

189 >>> ma.masked_all_like(arr) 

190 masked_array( 

191 data=[[--, --, --], 

192 [--, --, --]], 

193 mask=[[ True, True, True], 

194 [ True, True, True]], 

195 fill_value=1e+20, 

196 dtype=float32) 

197 

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

199 

200 >>> arr.dtype 

201 dtype('float32') 

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

203 dtype('float32') 

204 

205 """ 

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

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

208 return a 

209 

210 

211#####-------------------------------------------------------------------------- 

212#---- --- Standard functions --- 

213#####-------------------------------------------------------------------------- 

214class _fromnxfunction: 

215 """ 

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

217 

218 

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

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

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

222 

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

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

225 

226 Parameters 

227 ---------- 

228 funcname : str 

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

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

231 

232 """ 

233 

234 def __init__(self, funcname): 

235 self.__name__ = funcname 

236 self.__doc__ = self.getdoc() 

237 

238 def getdoc(self): 

239 """ 

240 Retrieve the docstring and signature from the function. 

241 

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

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

244 of the function to the mask is appended. 

245 

246 Parameters 

247 ---------- 

248 None 

249 

250 """ 

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

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

253 if doc: 253 ↛ 258line 253 didn't jump to line 258, because the condition on line 253 was never false

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

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

256 "and the _mask, if any.") 

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

258 return 

259 

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

261 pass 

262 

263 

264class _fromnxfunction_single(_fromnxfunction): 

265 """ 

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

267 argument followed by auxiliary args that are passed verbatim for 

268 both the data and mask calls. 

269 """ 

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

271 func = getattr(np, self.__name__) 

272 if isinstance(x, ndarray): 

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

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

275 return masked_array(_d, mask=_m) 

276 else: 

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

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

279 return masked_array(_d, mask=_m) 

280 

281 

282class _fromnxfunction_seq(_fromnxfunction): 

283 """ 

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

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

286 both the data and mask calls. 

287 """ 

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

289 func = getattr(np, self.__name__) 

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

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

292 return masked_array(_d, mask=_m) 

293 

294 

295class _fromnxfunction_args(_fromnxfunction): 

296 """ 

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

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

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

300 Array arguments are processed independently and the results are 

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

302 just the processed array instead of a list. 

303 """ 

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

305 func = getattr(np, self.__name__) 

306 arrays = [] 

307 args = list(args) 

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

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

310 res = [] 

311 for x in arrays: 

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

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

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

315 if len(arrays) == 1: 

316 return res[0] 

317 return res 

318 

319 

320class _fromnxfunction_allargs(_fromnxfunction): 

321 """ 

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

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

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

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

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

327 arguments are processed independently and the results are returned 

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

329 processed array instead of a list. 

330 """ 

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

332 func = getattr(np, self.__name__) 

333 res = [] 

334 for x in args: 

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

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

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

338 if len(args) == 1: 

339 return res[0] 

340 return res 

341 

342 

343atleast_1d = _fromnxfunction_allargs('atleast_1d') 

344atleast_2d = _fromnxfunction_allargs('atleast_2d') 

345atleast_3d = _fromnxfunction_allargs('atleast_3d') 

346 

347vstack = row_stack = _fromnxfunction_seq('vstack') 

348hstack = _fromnxfunction_seq('hstack') 

349column_stack = _fromnxfunction_seq('column_stack') 

350dstack = _fromnxfunction_seq('dstack') 

351stack = _fromnxfunction_seq('stack') 

352 

353hsplit = _fromnxfunction_single('hsplit') 

354 

355diagflat = _fromnxfunction_single('diagflat') 

356 

357 

358#####-------------------------------------------------------------------------- 

359#---- 

360#####-------------------------------------------------------------------------- 

361def flatten_inplace(seq): 

362 """Flatten a sequence in place.""" 

363 k = 0 

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

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

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

367 k += 1 

368 return seq 

369 

370 

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

372 """ 

373 (This docstring should be overwritten) 

374 """ 

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

376 nd = arr.ndim 

377 axis = normalize_axis_index(axis, nd) 

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

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

380 indlist = list(range(nd)) 

381 indlist.remove(axis) 

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

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

384 i.put(indlist, ind) 

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

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

387 asscalar = np.isscalar(res) 

388 if not asscalar: 

389 try: 

390 len(res) 

391 except TypeError: 

392 asscalar = True 

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

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

395 # just take the largest, to avoid some downcasting 

396 dtypes = [] 

397 if asscalar: 

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

399 outarr = zeros(outshape, object) 

400 outarr[tuple(ind)] = res 

401 Ntot = np.product(outshape) 

402 k = 1 

403 while k < Ntot: 

404 # increment the index 

405 ind[-1] += 1 

406 n = -1 

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

408 ind[n - 1] += 1 

409 ind[n] = 0 

410 n -= 1 

411 i.put(indlist, ind) 

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

413 outarr[tuple(ind)] = res 

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

415 k += 1 

416 else: 

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

418 j = i.copy() 

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

420 j.put(indlist, ind) 

421 Ntot = np.product(outshape) 

422 holdshape = outshape 

423 outshape = list(arr.shape) 

424 outshape[axis] = res.shape 

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

426 outshape = flatten_inplace(outshape) 

427 outarr = zeros(outshape, object) 

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

429 k = 1 

430 while k < Ntot: 

431 # increment the index 

432 ind[-1] += 1 

433 n = -1 

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

435 ind[n - 1] += 1 

436 ind[n] = 0 

437 n -= 1 

438 i.put(indlist, ind) 

439 j.put(indlist, ind) 

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

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

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

443 k += 1 

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

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

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

447 else: 

448 result = asarray(outarr, dtype=max_dtypes) 

449 result.fill_value = ma.default_fill_value(result) 

450 return result 

451apply_along_axis.__doc__ = np.apply_along_axis.__doc__ 

452 

453 

454def apply_over_axes(func, a, axes): 

455 """ 

456 (This docstring will be overwritten) 

457 """ 

458 val = asarray(a) 

459 N = a.ndim 

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

461 axes = (axes,) 

462 for axis in axes: 

463 if axis < 0: 

464 axis = N + axis 

465 args = (val, axis) 

466 res = func(*args) 

467 if res.ndim == val.ndim: 

468 val = res 

469 else: 

470 res = ma.expand_dims(res, axis) 

471 if res.ndim == val.ndim: 

472 val = res 

473 else: 

474 raise ValueError("function is not returning " 

475 "an array of the correct shape") 

476 return val 

477 

478 

479if apply_over_axes.__doc__ is not None: 479 ↛ 528line 479 didn't jump to line 528, because the condition on line 479 was never false

480 apply_over_axes.__doc__ = np.apply_over_axes.__doc__[ 

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

482 """ 

483 

484 Examples 

485 -------- 

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

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

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

489 >>> a 

490 masked_array( 

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

492 [--, --, --, --], 

493 [8, 9, 10, 11]], 

494 [[12, --, 14, 15], 

495 [--, --, --, --], 

496 [20, 21, 22, 23]]], 

497 mask=[[[False, True, False, False], 

498 [ True, True, True, True], 

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

500 [[False, True, False, False], 

501 [ True, True, True, True], 

502 [False, False, False, False]]], 

503 fill_value=999999) 

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

505 masked_array( 

506 data=[[[46], 

507 [--], 

508 [124]]], 

509 mask=[[[False], 

510 [ True], 

511 [False]]], 

512 fill_value=999999) 

513 

514 Tuple axis arguments to ufuncs are equivalent: 

515 

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

517 masked_array( 

518 data=[[[46], 

519 [--], 

520 [124]]], 

521 mask=[[[False], 

522 [ True], 

523 [False]]], 

524 fill_value=999999) 

525 """ 

526 

527 

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

529 keepdims=np._NoValue): 

530 """ 

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

532 

533 Parameters 

534 ---------- 

535 a : array_like 

536 Data to be averaged. 

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

538 axis : int, optional 

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

540 the flattened array. 

541 weights : array_like, optional 

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

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

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

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

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

547 

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

549 

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

551 returned : bool, optional 

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

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

554 Default is False. 

555 keepdims : bool, optional 

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

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

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

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

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

561 

562 .. versionadded:: 1.23.0 

563 

564 Returns 

565 ------- 

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

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

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

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

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

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

572 `float64`. 

573 

574 Examples 

575 -------- 

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

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

578 1.25 

579 

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

581 >>> x 

582 masked_array( 

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

584 [2., 3.], 

585 [4., 5.]], 

586 mask=False, 

587 fill_value=1e+20) 

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

589 ... returned=True) 

590 >>> avg 

591 masked_array(data=[2.6666666666666665, 3.6666666666666665], 

592 mask=[False, False], 

593 fill_value=1e+20) 

594 

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

596 

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

598 masked_array( 

599 data=[[0.5], 

600 [2.5], 

601 [4.5]], 

602 mask=False, 

603 fill_value=1e+20) 

604 """ 

605 a = asarray(a) 

606 m = getmask(a) 

607 

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

609 

610 if keepdims is np._NoValue: 

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

612 keepdims_kw = {} 

613 else: 

614 keepdims_kw = {'keepdims': keepdims} 

615 

616 if weights is None: 

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

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

619 else: 

620 wgt = asarray(weights) 

621 

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

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

624 else: 

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

626 

627 # Sanity checks 

628 if a.shape != wgt.shape: 

629 if axis is None: 

630 raise TypeError( 

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

632 "differ.") 

633 if wgt.ndim != 1: 

634 raise TypeError( 

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

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

637 raise ValueError( 

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

639 

640 # setup wgt to broadcast along axis 

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

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

643 

644 if m is not nomask: 

645 wgt = wgt*(~a.mask) 

646 wgt.mask |= a.mask 

647 

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

649 avg = np.multiply(a, wgt, 

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

651 

652 if returned: 

653 if scl.shape != avg.shape: 

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

655 return avg, scl 

656 else: 

657 return avg 

658 

659 

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

661 """ 

662 Compute the median along the specified axis. 

663 

664 Returns the median of the array elements. 

665 

666 Parameters 

667 ---------- 

668 a : array_like 

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

670 axis : int, optional 

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

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

673 out : ndarray, optional 

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

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

676 but the type will be cast if necessary. 

677 overwrite_input : bool, optional 

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

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

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

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

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

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

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

685 keepdims : bool, optional 

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

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

688 the result will broadcast correctly against the input array. 

689 

690 .. versionadded:: 1.10.0 

691 

692 Returns 

693 ------- 

694 median : ndarray 

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

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

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

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

699 

700 See Also 

701 -------- 

702 mean 

703 

704 Notes 

705 ----- 

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

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

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

709 when ``N`` is even. 

710 

711 Examples 

712 -------- 

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

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

715 1.5 

716 

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

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

719 2.5 

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

721 masked_array(data=[2.0, 5.0], 

722 mask=[False, False], 

723 fill_value=1e+20) 

724 

725 """ 

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

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

728 out=out, overwrite_input=overwrite_input, 

729 keepdims=keepdims) 

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

731 return masked_array(m, copy=False) 

732 else: 

733 return m 

734 

735 r, k = _ureduce(a, func=_median, axis=axis, out=out, 

736 overwrite_input=overwrite_input) 

737 if keepdims: 

738 return r.reshape(k) 

739 else: 

740 return r 

741 

742 

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

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

745 # values behind the mask 

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

747 fill_value = np.inf 

748 else: 

749 fill_value = None 

750 if overwrite_input: 

751 if axis is None: 

752 asorted = a.ravel() 

753 asorted.sort(fill_value=fill_value) 

754 else: 

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

756 asorted = a 

757 else: 

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

759 

760 if axis is None: 

761 axis = 0 

762 else: 

763 axis = normalize_axis_index(axis, asorted.ndim) 

764 

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

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

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

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

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

770 indexer = tuple(indexer) 

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

772 

773 if asorted.ndim == 1: 

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

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

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

777 # avoid inf / x = masked 

778 s = mid.sum(out=out) 

779 if not odd: 

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

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

782 else: 

783 s = mid.mean(out=out) 

784 

785 # if result is masked either the input contained enough 

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

787 # masked 

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

789 return np.ma.minimum_fill_value(asorted) 

790 return s 

791 

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

793 h = counts // 2 

794 

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

796 odd = counts % 2 == 1 

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

798 

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

800 

801 # get low and high median 

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

803 

804 def replace_masked(s): 

805 # Replace masked entries with minimum_full_value unless it all values 

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

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

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

809 if np.ma.is_masked(s): 

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

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

812 s.mask[rep] = False 

813 

814 replace_masked(low_high) 

815 

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

817 # avoid inf / x = masked 

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

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

820 

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

822 else: 

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

824 

825 return s 

826 

827 

828def compress_nd(x, axis=None): 

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

830 

831 Parameters 

832 ---------- 

833 x : array_like, MaskedArray 

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

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

836 set to `nomask`. 

837 axis : tuple of ints or int, optional 

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

839 parameter. 

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

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

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

843 

844 Returns 

845 ------- 

846 compress_array : ndarray 

847 The compressed array. 

848 """ 

849 x = asarray(x) 

850 m = getmask(x) 

851 # Set axis to tuple of ints 

852 if axis is None: 

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

854 else: 

855 axis = normalize_axis_tuple(axis, x.ndim) 

856 

857 # Nothing is masked: return x 

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

859 return x._data 

860 # All is masked: return empty 

861 if m.all(): 

862 return nxarray([]) 

863 # Filter elements through boolean indexing 

864 data = x._data 

865 for ax in axis: 

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

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

868 return data 

869 

870 

871def compress_rowcols(x, axis=None): 

872 """ 

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

874 masked values. 

875 

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

877 

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

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

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

881 

882 Parameters 

883 ---------- 

884 x : array_like, MaskedArray 

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

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

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

888 axis : int, optional 

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

890 

891 Returns 

892 ------- 

893 compressed_array : ndarray 

894 The compressed array. 

895 

896 Examples 

897 -------- 

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

899 ... [1, 0, 0], 

900 ... [0, 0, 0]]) 

901 >>> x 

902 masked_array( 

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

904 [--, 4, 5], 

905 [6, 7, 8]], 

906 mask=[[ True, False, False], 

907 [ True, False, False], 

908 [False, False, False]], 

909 fill_value=999999) 

910 

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

912 array([[7, 8]]) 

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

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

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

916 array([[1, 2], 

917 [4, 5], 

918 [7, 8]]) 

919 

920 """ 

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

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

923 return compress_nd(x, axis=axis) 

924 

925 

926def compress_rows(a): 

927 """ 

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

929 

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

931 `compress_rowcols` for details. 

932 

933 See Also 

934 -------- 

935 compress_rowcols 

936 

937 """ 

938 a = asarray(a) 

939 if a.ndim != 2: 

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

941 return compress_rowcols(a, 0) 

942 

943 

944def compress_cols(a): 

945 """ 

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

947 

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

949 `compress_rowcols` for details. 

950 

951 See Also 

952 -------- 

953 compress_rowcols 

954 

955 """ 

956 a = asarray(a) 

957 if a.ndim != 2: 

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

959 return compress_rowcols(a, 1) 

960 

961 

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

963 """ 

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

965 

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

967 

968 See Also 

969 -------- 

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

971 masked_where : Mask where a condition is met. 

972 

973 Examples 

974 -------- 

975 >>> import numpy.ma as ma 

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

977 >>> a[1, 1] = 1 

978 >>> a 

979 array([[0, 0, 0], 

980 [0, 1, 0], 

981 [0, 0, 0]]) 

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

983 >>> a 

984 masked_array( 

985 data=[[0, 0, 0], 

986 [0, --, 0], 

987 [0, 0, 0]], 

988 mask=[[False, False, False], 

989 [False, True, False], 

990 [False, False, False]], 

991 fill_value=1) 

992 

993 >>> ma.mask_rows(a) 

994 masked_array( 

995 data=[[0, 0, 0], 

996 [--, --, --], 

997 [0, 0, 0]], 

998 mask=[[False, False, False], 

999 [ True, True, True], 

1000 [False, False, False]], 

1001 fill_value=1) 

1002 

1003 """ 

1004 if axis is not np._NoValue: 

1005 # remove the axis argument when this deprecation expires 

1006 # NumPy 1.18.0, 2019-11-28 

1007 warnings.warn( 

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

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

1010 return mask_rowcols(a, 0) 

1011 

1012 

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

1014 """ 

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

1016 

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

1018 

1019 See Also 

1020 -------- 

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

1022 masked_where : Mask where a condition is met. 

1023 

1024 Examples 

1025 -------- 

1026 >>> import numpy.ma as ma 

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

1028 >>> a[1, 1] = 1 

1029 >>> a 

1030 array([[0, 0, 0], 

1031 [0, 1, 0], 

1032 [0, 0, 0]]) 

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

1034 >>> a 

1035 masked_array( 

1036 data=[[0, 0, 0], 

1037 [0, --, 0], 

1038 [0, 0, 0]], 

1039 mask=[[False, False, False], 

1040 [False, True, False], 

1041 [False, False, False]], 

1042 fill_value=1) 

1043 >>> ma.mask_cols(a) 

1044 masked_array( 

1045 data=[[0, --, 0], 

1046 [0, --, 0], 

1047 [0, --, 0]], 

1048 mask=[[False, True, False], 

1049 [False, True, False], 

1050 [False, True, False]], 

1051 fill_value=1) 

1052 

1053 """ 

1054 if axis is not np._NoValue: 

1055 # remove the axis argument when this deprecation expires 

1056 # NumPy 1.18.0, 2019-11-28 

1057 warnings.warn( 

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

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

1060 return mask_rowcols(a, 1) 

1061 

1062 

1063#####-------------------------------------------------------------------------- 

1064#---- --- arraysetops --- 

1065#####-------------------------------------------------------------------------- 

1066 

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

1068 """ 

1069 Compute the differences between consecutive elements of an array. 

1070 

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

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

1073 

1074 See Also 

1075 -------- 

1076 numpy.ediff1d : Equivalent function for ndarrays. 

1077 

1078 """ 

1079 arr = ma.asanyarray(arr).flat 

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

1081 arrays = [ed] 

1082 # 

1083 if to_begin is not None: 

1084 arrays.insert(0, to_begin) 

1085 if to_end is not None: 

1086 arrays.append(to_end) 

1087 # 

1088 if len(arrays) != 1: 

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

1090 # case where neither to_begin or to_end was given. 

1091 ed = hstack(arrays) 

1092 # 

1093 return ed 

1094 

1095 

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

1097 """ 

1098 Finds the unique elements of an array. 

1099 

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

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

1102 

1103 See Also 

1104 -------- 

1105 numpy.unique : Equivalent function for ndarrays. 

1106 

1107 """ 

1108 output = np.unique(ar1, 

1109 return_index=return_index, 

1110 return_inverse=return_inverse) 

1111 if isinstance(output, tuple): 

1112 output = list(output) 

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

1114 output = tuple(output) 

1115 else: 

1116 output = output.view(MaskedArray) 

1117 return output 

1118 

1119 

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

1121 """ 

1122 Returns the unique elements common to both arrays. 

1123 

1124 Masked values are considered equal one to the other. 

1125 The output is always a masked array. 

1126 

1127 See `numpy.intersect1d` for more details. 

1128 

1129 See Also 

1130 -------- 

1131 numpy.intersect1d : Equivalent function for ndarrays. 

1132 

1133 Examples 

1134 -------- 

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

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

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

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

1139 mask=[False, False, True], 

1140 fill_value=999999) 

1141 

1142 """ 

1143 if assume_unique: 

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

1145 else: 

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

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

1148 aux.sort() 

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

1150 

1151 

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

1153 """ 

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

1155 

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

1157 

1158 See Also 

1159 -------- 

1160 numpy.setxor1d : Equivalent function for ndarrays. 

1161 

1162 """ 

1163 if not assume_unique: 

1164 ar1 = unique(ar1) 

1165 ar2 = unique(ar2) 

1166 

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

1168 if aux.size == 0: 

1169 return aux 

1170 aux.sort() 

1171 auxf = aux.filled() 

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

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

1174# flag2 = ediff1d( flag ) == 0 

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

1176 return aux[flag2] 

1177 

1178 

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

1180 """ 

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

1182 array. 

1183 

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

1185 

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

1187 

1188 See Also 

1189 -------- 

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

1191 numpy.in1d : Equivalent function for ndarrays. 

1192 

1193 Notes 

1194 ----- 

1195 .. versionadded:: 1.4.0 

1196 

1197 """ 

1198 if not assume_unique: 

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

1200 ar2 = unique(ar2) 

1201 

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

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

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

1205 # the values from the second array. 

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

1207 sar = ar[order] 

1208 if invert: 

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

1210 else: 

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

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

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

1214 

1215 if assume_unique: 

1216 return flag[indx] 

1217 else: 

1218 return flag[indx][rev_idx] 

1219 

1220 

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

1222 """ 

1223 Calculates `element in test_elements`, broadcasting over 

1224 `element` only. 

1225 

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

1227 See `numpy.isin` for more details. 

1228 

1229 See Also 

1230 -------- 

1231 in1d : Flattened version of this function. 

1232 numpy.isin : Equivalent function for ndarrays. 

1233 

1234 Notes 

1235 ----- 

1236 .. versionadded:: 1.13.0 

1237 

1238 """ 

1239 element = ma.asarray(element) 

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

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

1242 

1243 

1244def union1d(ar1, ar2): 

1245 """ 

1246 Union of two arrays. 

1247 

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

1249 

1250 See Also 

1251 -------- 

1252 numpy.union1d : Equivalent function for ndarrays. 

1253 

1254 """ 

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

1256 

1257 

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

1259 """ 

1260 Set difference of 1D arrays with unique elements. 

1261 

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

1263 details. 

1264 

1265 See Also 

1266 -------- 

1267 numpy.setdiff1d : Equivalent function for ndarrays. 

1268 

1269 Examples 

1270 -------- 

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

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

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

1274 mask=[False, True], 

1275 fill_value=999999) 

1276 

1277 """ 

1278 if assume_unique: 

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

1280 else: 

1281 ar1 = unique(ar1) 

1282 ar2 = unique(ar2) 

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

1284 

1285 

1286############################################################################### 

1287# Covariance # 

1288############################################################################### 

1289 

1290 

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

1292 """ 

1293 Private function for the computation of covariance and correlation 

1294 coefficients. 

1295 

1296 """ 

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

1298 xmask = ma.getmaskarray(x) 

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

1300 if not allow_masked and xmask.any(): 

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

1302 # 

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

1304 rowvar = True 

1305 # Make sure that rowvar is either 0 or 1 

1306 rowvar = int(bool(rowvar)) 

1307 axis = 1 - rowvar 

1308 if rowvar: 

1309 tup = (slice(None), None) 

1310 else: 

1311 tup = (None, slice(None)) 

1312 # 

1313 if y is None: 

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

1315 else: 

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

1317 ymask = ma.getmaskarray(y) 

1318 if not allow_masked and ymask.any(): 

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

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

1321 if y.shape == x.shape: 

1322 # Define some common mask 

1323 common_mask = np.logical_or(xmask, ymask) 

1324 if common_mask is not nomask: 

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

1326 x._sharedmask = False 

1327 y._sharedmask = False 

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

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

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

1331 return (x, xnotmask, rowvar) 

1332 

1333 

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

1335 """ 

1336 Estimate the covariance matrix. 

1337 

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

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

1340 

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

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

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

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

1345 missing in either of the input arrays. 

1346 

1347 Parameters 

1348 ---------- 

1349 x : array_like 

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

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

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

1353 y : array_like, optional 

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

1355 shape as `x`. 

1356 rowvar : bool, optional 

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

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

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

1360 contain observations. 

1361 bias : bool, optional 

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

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

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

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

1366 allow_masked : bool, optional 

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

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

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

1370 ddof : {None, int}, optional 

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

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

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

1374 

1375 .. versionadded:: 1.5 

1376 

1377 Raises 

1378 ------ 

1379 ValueError 

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

1381 

1382 See Also 

1383 -------- 

1384 numpy.cov 

1385 

1386 """ 

1387 # Check inputs 

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

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

1390 # Set up ddof 

1391 if ddof is None: 

1392 if bias: 

1393 ddof = 0 

1394 else: 

1395 ddof = 1 

1396 

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

1398 if not rowvar: 

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

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

1401 else: 

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

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

1404 return result 

1405 

1406 

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

1408 ddof=np._NoValue): 

1409 """ 

1410 Return Pearson product-moment correlation coefficients. 

1411 

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

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

1414 

1415 Parameters 

1416 ---------- 

1417 x : array_like 

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

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

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

1421 y : array_like, optional 

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

1423 shape as `x`. 

1424 rowvar : bool, optional 

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

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

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

1428 contain observations. 

1429 bias : _NoValue, optional 

1430 Has no effect, do not use. 

1431 

1432 .. deprecated:: 1.10.0 

1433 allow_masked : bool, optional 

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

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

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

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

1438 ddof : _NoValue, optional 

1439 Has no effect, do not use. 

1440 

1441 .. deprecated:: 1.10.0 

1442 

1443 See Also 

1444 -------- 

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

1446 cov : Estimate the covariance matrix. 

1447 

1448 Notes 

1449 ----- 

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

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

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

1453 safely ignored in this and previous versions of numpy. 

1454 """ 

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

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

1457 # 2015-03-15, 1.10 

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

1459 # Get the data 

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

1461 # Compute the covariance matrix 

1462 if not rowvar: 

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

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

1465 else: 

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

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

1468 # Check whether we have a scalar 

1469 try: 

1470 diag = ma.diagonal(c) 

1471 except ValueError: 

1472 return 1 

1473 # 

1474 if xnotmask.all(): 

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

1476 else: 

1477 _denom = diagflat(diag) 

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

1479 n = x.shape[1 - rowvar] 

1480 if rowvar: 

1481 for i in range(n - 1): 

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

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

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

1485 else: 

1486 for i in range(n - 1): 

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

1488 _x = mask_cols( 

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

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

1491 return c / _denom 

1492 

1493#####-------------------------------------------------------------------------- 

1494#---- --- Concatenation helpers --- 

1495#####-------------------------------------------------------------------------- 

1496 

1497class MAxisConcatenator(AxisConcatenator): 

1498 """ 

1499 Translate slice objects to concatenation along an axis. 

1500 

1501 For documentation on usage, see `mr_class`. 

1502 

1503 See Also 

1504 -------- 

1505 mr_class 

1506 

1507 """ 

1508 concatenate = staticmethod(concatenate) 

1509 

1510 @classmethod 

1511 def makemat(cls, arr): 

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

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

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

1515 # with the .view) 

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

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

1518 

1519 def __getitem__(self, key): 

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

1521 if isinstance(key, str): 

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

1523 

1524 return super().__getitem__(key) 

1525 

1526 

1527class mr_class(MAxisConcatenator): 

1528 """ 

1529 Translate slice objects to concatenation along the first axis. 

1530 

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

1532 

1533 See Also 

1534 -------- 

1535 lib.index_tricks.RClass 

1536 

1537 Examples 

1538 -------- 

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

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

1541 mask=False, 

1542 fill_value=999999) 

1543 

1544 """ 

1545 def __init__(self): 

1546 MAxisConcatenator.__init__(self, 0) 

1547 

1548mr_ = mr_class() 

1549 

1550 

1551#####-------------------------------------------------------------------------- 

1552#---- Find unmasked data --- 

1553#####-------------------------------------------------------------------------- 

1554 

1555def ndenumerate(a, compressed=True): 

1556 """ 

1557 Multidimensional index iterator. 

1558 

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

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

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

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

1563 value of the underlying data array. 

1564 

1565 Notes 

1566 ----- 

1567 .. versionadded:: 1.23.0 

1568 

1569 Parameters 

1570 ---------- 

1571 a : array_like 

1572 An array with (possibly) masked elements. 

1573 compressed : bool, optional 

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

1575 

1576 See Also 

1577 -------- 

1578 numpy.ndenumerate : Equivalent function ignoring any mask. 

1579 

1580 Examples 

1581 -------- 

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

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

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

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

1586 >>> a 

1587 masked_array( 

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

1589 [--, 4, --], 

1590 [6, --, 8]], 

1591 mask=[[False, False, False], 

1592 [ True, False, True], 

1593 [False, True, False]], 

1594 fill_value=999999) 

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

1596 ... print(index, x) 

1597 (0, 0) 0 

1598 (0, 1) 1 

1599 (0, 2) 2 

1600 (1, 1) 4 

1601 (2, 0) 6 

1602 (2, 2) 8 

1603 

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

1605 ... print(index, x) 

1606 (0, 0) 0 

1607 (0, 1) 1 

1608 (0, 2) 2 

1609 (1, 0) -- 

1610 (1, 1) 4 

1611 (1, 2) -- 

1612 (2, 0) 6 

1613 (2, 1) -- 

1614 (2, 2) 8 

1615 """ 

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

1617 if not mask: 

1618 yield it 

1619 elif not compressed: 

1620 yield it[0], masked 

1621 

1622 

1623def flatnotmasked_edges(a): 

1624 """ 

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

1626 

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

1628 

1629 Parameters 

1630 ---------- 

1631 a : array_like 

1632 Input 1-D `MaskedArray` 

1633 

1634 Returns 

1635 ------- 

1636 edges : ndarray or None 

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

1638 Returns None if all values are masked. 

1639 

1640 See Also 

1641 -------- 

1642 flatnotmasked_contiguous, notmasked_contiguous, notmasked_edges 

1643 clump_masked, clump_unmasked 

1644 

1645 Notes 

1646 ----- 

1647 Only accepts 1-D arrays. 

1648 

1649 Examples 

1650 -------- 

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

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

1653 array([0, 9]) 

1654 

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

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

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

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

1659 

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

1661 array([3, 8]) 

1662 

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

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

1665 None 

1666 

1667 """ 

1668 m = getmask(a) 

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

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

1671 unmasked = np.flatnonzero(~m) 

1672 if len(unmasked) > 0: 

1673 return unmasked[[0, -1]] 

1674 else: 

1675 return None 

1676 

1677 

1678def notmasked_edges(a, axis=None): 

1679 """ 

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

1681 

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

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

1684 unmasked values respectively. 

1685 

1686 Parameters 

1687 ---------- 

1688 a : array_like 

1689 The input array. 

1690 axis : int, optional 

1691 Axis along which to perform the operation. 

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

1693 

1694 Returns 

1695 ------- 

1696 edges : ndarray or list 

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

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

1699 list of the first and last index. 

1700 

1701 See Also 

1702 -------- 

1703 flatnotmasked_contiguous, flatnotmasked_edges, notmasked_contiguous 

1704 clump_masked, clump_unmasked 

1705 

1706 Examples 

1707 -------- 

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

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

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

1711 

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

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

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

1715 

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

1717 array([0, 6]) 

1718 

1719 """ 

1720 a = asarray(a) 

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

1722 return flatnotmasked_edges(a) 

1723 m = getmaskarray(a) 

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

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

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

1727 

1728 

1729def flatnotmasked_contiguous(a): 

1730 """ 

1731 Find contiguous unmasked data in a masked array. 

1732 

1733 Parameters 

1734 ---------- 

1735 a : array_like 

1736 The input array. 

1737 

1738 Returns 

1739 ------- 

1740 slice_list : list 

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

1742 

1743 .. versionchanged:: 1.15.0 

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

1745 

1746 See Also 

1747 -------- 

1748 flatnotmasked_edges, notmasked_contiguous, notmasked_edges 

1749 clump_masked, clump_unmasked 

1750 

1751 Notes 

1752 ----- 

1753 Only accepts 2-D arrays at most. 

1754 

1755 Examples 

1756 -------- 

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

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

1759 [slice(0, 10, None)] 

1760 

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

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

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

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

1765 

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

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

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

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

1770 [] 

1771 

1772 """ 

1773 m = getmask(a) 

1774 if m is nomask: 

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

1776 i = 0 

1777 result = [] 

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

1779 n = len(list(g)) 

1780 if not k: 

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

1782 i += n 

1783 return result 

1784 

1785 

1786def notmasked_contiguous(a, axis=None): 

1787 """ 

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

1789 

1790 Parameters 

1791 ---------- 

1792 a : array_like 

1793 The input array. 

1794 axis : int, optional 

1795 Axis along which to perform the operation. 

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

1797 is the same as `flatnotmasked_contiguous`. 

1798 

1799 Returns 

1800 ------- 

1801 endpoints : list 

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

1803 in the array. 

1804 

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

1806 

1807 See Also 

1808 -------- 

1809 flatnotmasked_edges, flatnotmasked_contiguous, notmasked_edges 

1810 clump_masked, clump_unmasked 

1811 

1812 Notes 

1813 ----- 

1814 Only accepts 2-D arrays at most. 

1815 

1816 Examples 

1817 -------- 

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

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

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

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

1822 >>> ma 

1823 masked_array( 

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

1825 [--, --, --, 7], 

1826 [8, --, --, 11]], 

1827 mask=[[False, True, False, False], 

1828 [ True, True, True, False], 

1829 [False, True, True, False]], 

1830 fill_value=999999) 

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

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

1833 

1834 >>> np.ma.notmasked_contiguous(ma) 

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

1836 

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

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

1839 

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

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

1842 

1843 """ 

1844 a = asarray(a) 

1845 nd = a.ndim 

1846 if nd > 2: 

1847 raise NotImplementedError("Currently limited to atmost 2D array.") 

1848 if axis is None or nd == 1: 

1849 return flatnotmasked_contiguous(a) 

1850 # 

1851 result = [] 

1852 # 

1853 other = (axis + 1) % 2 

1854 idx = [0, 0] 

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

1856 # 

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

1858 idx[other] = i 

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

1860 return result 

1861 

1862 

1863def _ezclump(mask): 

1864 """ 

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

1866 

1867 Returns a series of slices. 

1868 """ 

1869 if mask.ndim > 1: 

1870 mask = mask.ravel() 

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

1872 idx = idx[0] + 1 

1873 

1874 if mask[0]: 

1875 if len(idx) == 0: 

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

1877 

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

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

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

1881 else: 

1882 if len(idx) == 0: 

1883 return [] 

1884 

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

1886 

1887 if mask[-1]: 

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

1889 return r 

1890 

1891 

1892def clump_unmasked(a): 

1893 """ 

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

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

1896 

1897 Parameters 

1898 ---------- 

1899 a : ndarray 

1900 A one-dimensional masked array. 

1901 

1902 Returns 

1903 ------- 

1904 slices : list of slice 

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

1906 elements in `a`. 

1907 

1908 Notes 

1909 ----- 

1910 .. versionadded:: 1.4.0 

1911 

1912 See Also 

1913 -------- 

1914 flatnotmasked_edges, flatnotmasked_contiguous, notmasked_edges 

1915 notmasked_contiguous, clump_masked 

1916 

1917 Examples 

1918 -------- 

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

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

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

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

1923 

1924 """ 

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

1926 if mask is nomask: 

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

1928 return _ezclump(~mask) 

1929 

1930 

1931def clump_masked(a): 

1932 """ 

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

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

1935 

1936 Parameters 

1937 ---------- 

1938 a : ndarray 

1939 A one-dimensional masked array. 

1940 

1941 Returns 

1942 ------- 

1943 slices : list of slice 

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

1945 in `a`. 

1946 

1947 Notes 

1948 ----- 

1949 .. versionadded:: 1.4.0 

1950 

1951 See Also 

1952 -------- 

1953 flatnotmasked_edges, flatnotmasked_contiguous, notmasked_edges 

1954 notmasked_contiguous, clump_unmasked 

1955 

1956 Examples 

1957 -------- 

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

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

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

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

1962 

1963 """ 

1964 mask = ma.getmask(a) 

1965 if mask is nomask: 

1966 return [] 

1967 return _ezclump(mask) 

1968 

1969 

1970############################################################################### 

1971# Polynomial fit # 

1972############################################################################### 

1973 

1974 

1975def vander(x, n=None): 

1976 """ 

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

1978 

1979 """ 

1980 _vander = np.vander(x, n) 

1981 m = getmask(x) 

1982 if m is not nomask: 

1983 _vander[m] = 0 

1984 return _vander 

1985 

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

1987 

1988 

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

1990 """ 

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

1992 

1993 """ 

1994 x = asarray(x) 

1995 y = asarray(y) 

1996 

1997 m = getmask(x) 

1998 if y.ndim == 1: 

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

2000 elif y.ndim == 2: 

2001 my = getmask(mask_rows(y)) 

2002 if my is not nomask: 

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

2004 else: 

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

2006 

2007 if w is not None: 

2008 w = asarray(w) 

2009 if w.ndim != 1: 

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

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

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

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

2014 

2015 if m is not nomask: 

2016 not_m = ~m 

2017 if w is not None: 

2018 w = w[not_m] 

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

2020 else: 

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

2022 

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