annotate DEPENDENCIES/mingw32/Python27/Lib/site-packages/numpy/ma/extras.py @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents 2a2c65a20a8b
children
rev   line source
Chris@87 1 """
Chris@87 2 Masked arrays add-ons.
Chris@87 3
Chris@87 4 A collection of utilities for `numpy.ma`.
Chris@87 5
Chris@87 6 :author: Pierre Gerard-Marchant
Chris@87 7 :contact: pierregm_at_uga_dot_edu
Chris@87 8 :version: $Id: extras.py 3473 2007-10-29 15:18:13Z jarrod.millman $
Chris@87 9
Chris@87 10 """
Chris@87 11 from __future__ import division, absolute_import, print_function
Chris@87 12
Chris@87 13 __author__ = "Pierre GF Gerard-Marchant ($Author: jarrod.millman $)"
Chris@87 14 __version__ = '1.0'
Chris@87 15 __revision__ = "$Revision: 3473 $"
Chris@87 16 __date__ = '$Date: 2007-10-29 17:18:13 +0200 (Mon, 29 Oct 2007) $'
Chris@87 17
Chris@87 18 __all__ = ['apply_along_axis', 'apply_over_axes', 'atleast_1d', 'atleast_2d',
Chris@87 19 'atleast_3d', 'average',
Chris@87 20 'clump_masked', 'clump_unmasked', 'column_stack', 'compress_cols',
Chris@87 21 'compress_rowcols', 'compress_rows', 'count_masked', 'corrcoef',
Chris@87 22 'cov',
Chris@87 23 'diagflat', 'dot', 'dstack',
Chris@87 24 'ediff1d',
Chris@87 25 'flatnotmasked_contiguous', 'flatnotmasked_edges',
Chris@87 26 'hsplit', 'hstack',
Chris@87 27 'in1d', 'intersect1d',
Chris@87 28 'mask_cols', 'mask_rowcols', 'mask_rows', 'masked_all',
Chris@87 29 'masked_all_like', 'median', 'mr_',
Chris@87 30 'notmasked_contiguous', 'notmasked_edges',
Chris@87 31 'polyfit',
Chris@87 32 'row_stack',
Chris@87 33 'setdiff1d', 'setxor1d',
Chris@87 34 'unique', 'union1d',
Chris@87 35 'vander', 'vstack',
Chris@87 36 ]
Chris@87 37
Chris@87 38 import itertools
Chris@87 39 import warnings
Chris@87 40
Chris@87 41 from . import core as ma
Chris@87 42 from .core import MaskedArray, MAError, add, array, asarray, concatenate, count, \
Chris@87 43 filled, getmask, getmaskarray, make_mask_descr, masked, masked_array, \
Chris@87 44 mask_or, nomask, ones, sort, zeros
Chris@87 45 #from core import *
Chris@87 46
Chris@87 47 import numpy as np
Chris@87 48 from numpy import ndarray, array as nxarray
Chris@87 49 import numpy.core.umath as umath
Chris@87 50 from numpy.lib.index_tricks import AxisConcatenator
Chris@87 51 from numpy.linalg import lstsq
Chris@87 52
Chris@87 53
Chris@87 54 #...............................................................................
Chris@87 55 def issequence(seq):
Chris@87 56 """Is seq a sequence (ndarray, list or tuple)?"""
Chris@87 57 if isinstance(seq, (ndarray, tuple, list)):
Chris@87 58 return True
Chris@87 59 return False
Chris@87 60
Chris@87 61 def count_masked(arr, axis=None):
Chris@87 62 """
Chris@87 63 Count the number of masked elements along the given axis.
Chris@87 64
Chris@87 65 Parameters
Chris@87 66 ----------
Chris@87 67 arr : array_like
Chris@87 68 An array with (possibly) masked elements.
Chris@87 69 axis : int, optional
Chris@87 70 Axis along which to count. If None (default), a flattened
Chris@87 71 version of the array is used.
Chris@87 72
Chris@87 73 Returns
Chris@87 74 -------
Chris@87 75 count : int, ndarray
Chris@87 76 The total number of masked elements (axis=None) or the number
Chris@87 77 of masked elements along each slice of the given axis.
Chris@87 78
Chris@87 79 See Also
Chris@87 80 --------
Chris@87 81 MaskedArray.count : Count non-masked elements.
Chris@87 82
Chris@87 83 Examples
Chris@87 84 --------
Chris@87 85 >>> import numpy.ma as ma
Chris@87 86 >>> a = np.arange(9).reshape((3,3))
Chris@87 87 >>> a = ma.array(a)
Chris@87 88 >>> a[1, 0] = ma.masked
Chris@87 89 >>> a[1, 2] = ma.masked
Chris@87 90 >>> a[2, 1] = ma.masked
Chris@87 91 >>> a
Chris@87 92 masked_array(data =
Chris@87 93 [[0 1 2]
Chris@87 94 [-- 4 --]
Chris@87 95 [6 -- 8]],
Chris@87 96 mask =
Chris@87 97 [[False False False]
Chris@87 98 [ True False True]
Chris@87 99 [False True False]],
Chris@87 100 fill_value=999999)
Chris@87 101 >>> ma.count_masked(a)
Chris@87 102 3
Chris@87 103
Chris@87 104 When the `axis` keyword is used an array is returned.
Chris@87 105
Chris@87 106 >>> ma.count_masked(a, axis=0)
Chris@87 107 array([1, 1, 1])
Chris@87 108 >>> ma.count_masked(a, axis=1)
Chris@87 109 array([0, 2, 1])
Chris@87 110
Chris@87 111 """
Chris@87 112 m = getmaskarray(arr)
Chris@87 113 return m.sum(axis)
Chris@87 114
Chris@87 115 def masked_all(shape, dtype=float):
Chris@87 116 """
Chris@87 117 Empty masked array with all elements masked.
Chris@87 118
Chris@87 119 Return an empty masked array of the given shape and dtype, where all the
Chris@87 120 data are masked.
Chris@87 121
Chris@87 122 Parameters
Chris@87 123 ----------
Chris@87 124 shape : tuple
Chris@87 125 Shape of the required MaskedArray.
Chris@87 126 dtype : dtype, optional
Chris@87 127 Data type of the output.
Chris@87 128
Chris@87 129 Returns
Chris@87 130 -------
Chris@87 131 a : MaskedArray
Chris@87 132 A masked array with all data masked.
Chris@87 133
Chris@87 134 See Also
Chris@87 135 --------
Chris@87 136 masked_all_like : Empty masked array modelled on an existing array.
Chris@87 137
Chris@87 138 Examples
Chris@87 139 --------
Chris@87 140 >>> import numpy.ma as ma
Chris@87 141 >>> ma.masked_all((3, 3))
Chris@87 142 masked_array(data =
Chris@87 143 [[-- -- --]
Chris@87 144 [-- -- --]
Chris@87 145 [-- -- --]],
Chris@87 146 mask =
Chris@87 147 [[ True True True]
Chris@87 148 [ True True True]
Chris@87 149 [ True True True]],
Chris@87 150 fill_value=1e+20)
Chris@87 151
Chris@87 152 The `dtype` parameter defines the underlying data type.
Chris@87 153
Chris@87 154 >>> a = ma.masked_all((3, 3))
Chris@87 155 >>> a.dtype
Chris@87 156 dtype('float64')
Chris@87 157 >>> a = ma.masked_all((3, 3), dtype=np.int32)
Chris@87 158 >>> a.dtype
Chris@87 159 dtype('int32')
Chris@87 160
Chris@87 161 """
Chris@87 162 a = masked_array(np.empty(shape, dtype),
Chris@87 163 mask=np.ones(shape, make_mask_descr(dtype)))
Chris@87 164 return a
Chris@87 165
Chris@87 166 def masked_all_like(arr):
Chris@87 167 """
Chris@87 168 Empty masked array with the properties of an existing array.
Chris@87 169
Chris@87 170 Return an empty masked array of the same shape and dtype as
Chris@87 171 the array `arr`, where all the data are masked.
Chris@87 172
Chris@87 173 Parameters
Chris@87 174 ----------
Chris@87 175 arr : ndarray
Chris@87 176 An array describing the shape and dtype of the required MaskedArray.
Chris@87 177
Chris@87 178 Returns
Chris@87 179 -------
Chris@87 180 a : MaskedArray
Chris@87 181 A masked array with all data masked.
Chris@87 182
Chris@87 183 Raises
Chris@87 184 ------
Chris@87 185 AttributeError
Chris@87 186 If `arr` doesn't have a shape attribute (i.e. not an ndarray)
Chris@87 187
Chris@87 188 See Also
Chris@87 189 --------
Chris@87 190 masked_all : Empty masked array with all elements masked.
Chris@87 191
Chris@87 192 Examples
Chris@87 193 --------
Chris@87 194 >>> import numpy.ma as ma
Chris@87 195 >>> arr = np.zeros((2, 3), dtype=np.float32)
Chris@87 196 >>> arr
Chris@87 197 array([[ 0., 0., 0.],
Chris@87 198 [ 0., 0., 0.]], dtype=float32)
Chris@87 199 >>> ma.masked_all_like(arr)
Chris@87 200 masked_array(data =
Chris@87 201 [[-- -- --]
Chris@87 202 [-- -- --]],
Chris@87 203 mask =
Chris@87 204 [[ True True True]
Chris@87 205 [ True True True]],
Chris@87 206 fill_value=1e+20)
Chris@87 207
Chris@87 208 The dtype of the masked array matches the dtype of `arr`.
Chris@87 209
Chris@87 210 >>> arr.dtype
Chris@87 211 dtype('float32')
Chris@87 212 >>> ma.masked_all_like(arr).dtype
Chris@87 213 dtype('float32')
Chris@87 214
Chris@87 215 """
Chris@87 216 a = np.empty_like(arr).view(MaskedArray)
Chris@87 217 a._mask = np.ones(a.shape, dtype=make_mask_descr(a.dtype))
Chris@87 218 return a
Chris@87 219
Chris@87 220
Chris@87 221 #####--------------------------------------------------------------------------
Chris@87 222 #---- --- Standard functions ---
Chris@87 223 #####--------------------------------------------------------------------------
Chris@87 224 class _fromnxfunction:
Chris@87 225 """
Chris@87 226 Defines a wrapper to adapt NumPy functions to masked arrays.
Chris@87 227
Chris@87 228
Chris@87 229 An instance of `_fromnxfunction` can be called with the same parameters
Chris@87 230 as the wrapped NumPy function. The docstring of `newfunc` is adapted from
Chris@87 231 the wrapped function as well, see `getdoc`.
Chris@87 232
Chris@87 233 Parameters
Chris@87 234 ----------
Chris@87 235 funcname : str
Chris@87 236 The name of the function to be adapted. The function should be
Chris@87 237 in the NumPy namespace (i.e. ``np.funcname``).
Chris@87 238
Chris@87 239 """
Chris@87 240
Chris@87 241 def __init__(self, funcname):
Chris@87 242 self.__name__ = funcname
Chris@87 243 self.__doc__ = self.getdoc()
Chris@87 244
Chris@87 245 def getdoc(self):
Chris@87 246 """
Chris@87 247 Retrieve the docstring and signature from the function.
Chris@87 248
Chris@87 249 The ``__doc__`` attribute of the function is used as the docstring for
Chris@87 250 the new masked array version of the function. A note on application
Chris@87 251 of the function to the mask is appended.
Chris@87 252
Chris@87 253 .. warning::
Chris@87 254 If the function docstring already contained a Notes section, the
Chris@87 255 new docstring will have two Notes sections instead of appending a note
Chris@87 256 to the existing section.
Chris@87 257
Chris@87 258 Parameters
Chris@87 259 ----------
Chris@87 260 None
Chris@87 261
Chris@87 262 """
Chris@87 263 npfunc = getattr(np, self.__name__, None)
Chris@87 264 doc = getattr(npfunc, '__doc__', None)
Chris@87 265 if doc:
Chris@87 266 sig = self.__name__ + ma.get_object_signature(npfunc)
Chris@87 267 locdoc = "Notes\n-----\nThe function is applied to both the _data"\
Chris@87 268 " and the _mask, if any."
Chris@87 269 return '\n'.join((sig, doc, locdoc))
Chris@87 270 return
Chris@87 271
Chris@87 272
Chris@87 273 def __call__(self, *args, **params):
Chris@87 274 func = getattr(np, self.__name__)
Chris@87 275 if len(args) == 1:
Chris@87 276 x = args[0]
Chris@87 277 if isinstance(x, ndarray):
Chris@87 278 _d = func(x.__array__(), **params)
Chris@87 279 _m = func(getmaskarray(x), **params)
Chris@87 280 return masked_array(_d, mask=_m)
Chris@87 281 elif isinstance(x, tuple) or isinstance(x, list):
Chris@87 282 _d = func(tuple([np.asarray(a) for a in x]), **params)
Chris@87 283 _m = func(tuple([getmaskarray(a) for a in x]), **params)
Chris@87 284 return masked_array(_d, mask=_m)
Chris@87 285 else:
Chris@87 286 arrays = []
Chris@87 287 args = list(args)
Chris@87 288 while len(args) > 0 and issequence(args[0]):
Chris@87 289 arrays.append(args.pop(0))
Chris@87 290 res = []
Chris@87 291 for x in arrays:
Chris@87 292 _d = func(np.asarray(x), *args, **params)
Chris@87 293 _m = func(getmaskarray(x), *args, **params)
Chris@87 294 res.append(masked_array(_d, mask=_m))
Chris@87 295 return res
Chris@87 296
Chris@87 297 atleast_1d = _fromnxfunction('atleast_1d')
Chris@87 298 atleast_2d = _fromnxfunction('atleast_2d')
Chris@87 299 atleast_3d = _fromnxfunction('atleast_3d')
Chris@87 300 #atleast_1d = np.atleast_1d
Chris@87 301 #atleast_2d = np.atleast_2d
Chris@87 302 #atleast_3d = np.atleast_3d
Chris@87 303
Chris@87 304 vstack = row_stack = _fromnxfunction('vstack')
Chris@87 305 hstack = _fromnxfunction('hstack')
Chris@87 306 column_stack = _fromnxfunction('column_stack')
Chris@87 307 dstack = _fromnxfunction('dstack')
Chris@87 308
Chris@87 309 hsplit = _fromnxfunction('hsplit')
Chris@87 310
Chris@87 311 diagflat = _fromnxfunction('diagflat')
Chris@87 312
Chris@87 313
Chris@87 314 #####--------------------------------------------------------------------------
Chris@87 315 #----
Chris@87 316 #####--------------------------------------------------------------------------
Chris@87 317 def flatten_inplace(seq):
Chris@87 318 """Flatten a sequence in place."""
Chris@87 319 k = 0
Chris@87 320 while (k != len(seq)):
Chris@87 321 while hasattr(seq[k], '__iter__'):
Chris@87 322 seq[k:(k + 1)] = seq[k]
Chris@87 323 k += 1
Chris@87 324 return seq
Chris@87 325
Chris@87 326
Chris@87 327 def apply_along_axis(func1d, axis, arr, *args, **kwargs):
Chris@87 328 """
Chris@87 329 (This docstring should be overwritten)
Chris@87 330 """
Chris@87 331 arr = array(arr, copy=False, subok=True)
Chris@87 332 nd = arr.ndim
Chris@87 333 if axis < 0:
Chris@87 334 axis += nd
Chris@87 335 if (axis >= nd):
Chris@87 336 raise ValueError("axis must be less than arr.ndim; axis=%d, rank=%d."
Chris@87 337 % (axis, nd))
Chris@87 338 ind = [0] * (nd - 1)
Chris@87 339 i = np.zeros(nd, 'O')
Chris@87 340 indlist = list(range(nd))
Chris@87 341 indlist.remove(axis)
Chris@87 342 i[axis] = slice(None, None)
Chris@87 343 outshape = np.asarray(arr.shape).take(indlist)
Chris@87 344 i.put(indlist, ind)
Chris@87 345 j = i.copy()
Chris@87 346 res = func1d(arr[tuple(i.tolist())], *args, **kwargs)
Chris@87 347 # if res is a number, then we have a smaller output array
Chris@87 348 asscalar = np.isscalar(res)
Chris@87 349 if not asscalar:
Chris@87 350 try:
Chris@87 351 len(res)
Chris@87 352 except TypeError:
Chris@87 353 asscalar = True
Chris@87 354 # Note: we shouldn't set the dtype of the output from the first result...
Chris@87 355 #...so we force the type to object, and build a list of dtypes
Chris@87 356 #...we'll just take the largest, to avoid some downcasting
Chris@87 357 dtypes = []
Chris@87 358 if asscalar:
Chris@87 359 dtypes.append(np.asarray(res).dtype)
Chris@87 360 outarr = zeros(outshape, object)
Chris@87 361 outarr[tuple(ind)] = res
Chris@87 362 Ntot = np.product(outshape)
Chris@87 363 k = 1
Chris@87 364 while k < Ntot:
Chris@87 365 # increment the index
Chris@87 366 ind[-1] += 1
Chris@87 367 n = -1
Chris@87 368 while (ind[n] >= outshape[n]) and (n > (1 - nd)):
Chris@87 369 ind[n - 1] += 1
Chris@87 370 ind[n] = 0
Chris@87 371 n -= 1
Chris@87 372 i.put(indlist, ind)
Chris@87 373 res = func1d(arr[tuple(i.tolist())], *args, **kwargs)
Chris@87 374 outarr[tuple(ind)] = res
Chris@87 375 dtypes.append(asarray(res).dtype)
Chris@87 376 k += 1
Chris@87 377 else:
Chris@87 378 res = array(res, copy=False, subok=True)
Chris@87 379 j = i.copy()
Chris@87 380 j[axis] = ([slice(None, None)] * res.ndim)
Chris@87 381 j.put(indlist, ind)
Chris@87 382 Ntot = np.product(outshape)
Chris@87 383 holdshape = outshape
Chris@87 384 outshape = list(arr.shape)
Chris@87 385 outshape[axis] = res.shape
Chris@87 386 dtypes.append(asarray(res).dtype)
Chris@87 387 outshape = flatten_inplace(outshape)
Chris@87 388 outarr = zeros(outshape, object)
Chris@87 389 outarr[tuple(flatten_inplace(j.tolist()))] = res
Chris@87 390 k = 1
Chris@87 391 while k < Ntot:
Chris@87 392 # increment the index
Chris@87 393 ind[-1] += 1
Chris@87 394 n = -1
Chris@87 395 while (ind[n] >= holdshape[n]) and (n > (1 - nd)):
Chris@87 396 ind[n - 1] += 1
Chris@87 397 ind[n] = 0
Chris@87 398 n -= 1
Chris@87 399 i.put(indlist, ind)
Chris@87 400 j.put(indlist, ind)
Chris@87 401 res = func1d(arr[tuple(i.tolist())], *args, **kwargs)
Chris@87 402 outarr[tuple(flatten_inplace(j.tolist()))] = res
Chris@87 403 dtypes.append(asarray(res).dtype)
Chris@87 404 k += 1
Chris@87 405 max_dtypes = np.dtype(np.asarray(dtypes).max())
Chris@87 406 if not hasattr(arr, '_mask'):
Chris@87 407 result = np.asarray(outarr, dtype=max_dtypes)
Chris@87 408 else:
Chris@87 409 result = asarray(outarr, dtype=max_dtypes)
Chris@87 410 result.fill_value = ma.default_fill_value(result)
Chris@87 411 return result
Chris@87 412 apply_along_axis.__doc__ = np.apply_along_axis.__doc__
Chris@87 413
Chris@87 414
Chris@87 415 def apply_over_axes(func, a, axes):
Chris@87 416 """
Chris@87 417 (This docstring will be overwritten)
Chris@87 418 """
Chris@87 419 val = asarray(a)
Chris@87 420 N = a.ndim
Chris@87 421 if array(axes).ndim == 0:
Chris@87 422 axes = (axes,)
Chris@87 423 for axis in axes:
Chris@87 424 if axis < 0: axis = N + axis
Chris@87 425 args = (val, axis)
Chris@87 426 res = func(*args)
Chris@87 427 if res.ndim == val.ndim:
Chris@87 428 val = res
Chris@87 429 else:
Chris@87 430 res = ma.expand_dims(res, axis)
Chris@87 431 if res.ndim == val.ndim:
Chris@87 432 val = res
Chris@87 433 else:
Chris@87 434 raise ValueError("function is not returning "
Chris@87 435 "an array of the correct shape")
Chris@87 436 return val
Chris@87 437
Chris@87 438 if apply_over_axes.__doc__ is not None:
Chris@87 439 apply_over_axes.__doc__ = np.apply_over_axes.__doc__[
Chris@87 440 :np.apply_over_axes.__doc__.find('Notes')].rstrip() + \
Chris@87 441 """
Chris@87 442
Chris@87 443 Examples
Chris@87 444 --------
Chris@87 445 >>> a = ma.arange(24).reshape(2,3,4)
Chris@87 446 >>> a[:,0,1] = ma.masked
Chris@87 447 >>> a[:,1,:] = ma.masked
Chris@87 448 >>> print a
Chris@87 449 [[[0 -- 2 3]
Chris@87 450 [-- -- -- --]
Chris@87 451 [8 9 10 11]]
Chris@87 452
Chris@87 453 [[12 -- 14 15]
Chris@87 454 [-- -- -- --]
Chris@87 455 [20 21 22 23]]]
Chris@87 456 >>> print ma.apply_over_axes(ma.sum, a, [0,2])
Chris@87 457 [[[46]
Chris@87 458 [--]
Chris@87 459 [124]]]
Chris@87 460
Chris@87 461 Tuple axis arguments to ufuncs are equivalent:
Chris@87 462
Chris@87 463 >>> print ma.sum(a, axis=(0,2)).reshape((1,-1,1))
Chris@87 464 [[[46]
Chris@87 465 [--]
Chris@87 466 [124]]]
Chris@87 467 """
Chris@87 468
Chris@87 469
Chris@87 470 def average(a, axis=None, weights=None, returned=False):
Chris@87 471 """
Chris@87 472 Return the weighted average of array over the given axis.
Chris@87 473
Chris@87 474 Parameters
Chris@87 475 ----------
Chris@87 476 a : array_like
Chris@87 477 Data to be averaged.
Chris@87 478 Masked entries are not taken into account in the computation.
Chris@87 479 axis : int, optional
Chris@87 480 Axis along which the average is computed. The default is to compute
Chris@87 481 the average of the flattened array.
Chris@87 482 weights : array_like, optional
Chris@87 483 The importance that each element has in the computation of the average.
Chris@87 484 The weights array can either be 1-D (in which case its length must be
Chris@87 485 the size of `a` along the given axis) or of the same shape as `a`.
Chris@87 486 If ``weights=None``, then all data in `a` are assumed to have a
Chris@87 487 weight equal to one. If `weights` is complex, the imaginary parts
Chris@87 488 are ignored.
Chris@87 489 returned : bool, optional
Chris@87 490 Flag indicating whether a tuple ``(result, sum of weights)``
Chris@87 491 should be returned as output (True), or just the result (False).
Chris@87 492 Default is False.
Chris@87 493
Chris@87 494 Returns
Chris@87 495 -------
Chris@87 496 average, [sum_of_weights] : (tuple of) scalar or MaskedArray
Chris@87 497 The average along the specified axis. When returned is `True`,
Chris@87 498 return a tuple with the average as the first element and the sum
Chris@87 499 of the weights as the second element. The return type is `np.float64`
Chris@87 500 if `a` is of integer type, otherwise it is of the same type as `a`.
Chris@87 501 If returned, `sum_of_weights` is of the same type as `average`.
Chris@87 502
Chris@87 503 Examples
Chris@87 504 --------
Chris@87 505 >>> a = np.ma.array([1., 2., 3., 4.], mask=[False, False, True, True])
Chris@87 506 >>> np.ma.average(a, weights=[3, 1, 0, 0])
Chris@87 507 1.25
Chris@87 508
Chris@87 509 >>> x = np.ma.arange(6.).reshape(3, 2)
Chris@87 510 >>> print x
Chris@87 511 [[ 0. 1.]
Chris@87 512 [ 2. 3.]
Chris@87 513 [ 4. 5.]]
Chris@87 514 >>> avg, sumweights = np.ma.average(x, axis=0, weights=[1, 2, 3],
Chris@87 515 ... returned=True)
Chris@87 516 >>> print avg
Chris@87 517 [2.66666666667 3.66666666667]
Chris@87 518
Chris@87 519 """
Chris@87 520 a = asarray(a)
Chris@87 521 mask = a.mask
Chris@87 522 ash = a.shape
Chris@87 523 if ash == ():
Chris@87 524 ash = (1,)
Chris@87 525 if axis is None:
Chris@87 526 if mask is nomask:
Chris@87 527 if weights is None:
Chris@87 528 n = a.sum(axis=None)
Chris@87 529 d = float(a.size)
Chris@87 530 else:
Chris@87 531 w = filled(weights, 0.0).ravel()
Chris@87 532 n = umath.add.reduce(a._data.ravel() * w)
Chris@87 533 d = umath.add.reduce(w)
Chris@87 534 del w
Chris@87 535 else:
Chris@87 536 if weights is None:
Chris@87 537 n = a.filled(0).sum(axis=None)
Chris@87 538 d = float(umath.add.reduce((~mask).ravel()))
Chris@87 539 else:
Chris@87 540 w = array(filled(weights, 0.0), float, mask=mask).ravel()
Chris@87 541 n = add.reduce(a.ravel() * w)
Chris@87 542 d = add.reduce(w)
Chris@87 543 del w
Chris@87 544 else:
Chris@87 545 if mask is nomask:
Chris@87 546 if weights is None:
Chris@87 547 d = ash[axis] * 1.0
Chris@87 548 n = add.reduce(a._data, axis)
Chris@87 549 else:
Chris@87 550 w = filled(weights, 0.0)
Chris@87 551 wsh = w.shape
Chris@87 552 if wsh == ():
Chris@87 553 wsh = (1,)
Chris@87 554 if wsh == ash:
Chris@87 555 w = np.array(w, float, copy=0)
Chris@87 556 n = add.reduce(a * w, axis)
Chris@87 557 d = add.reduce(w, axis)
Chris@87 558 del w
Chris@87 559 elif wsh == (ash[axis],):
Chris@87 560 ni = ash[axis]
Chris@87 561 r = [None] * len(ash)
Chris@87 562 r[axis] = slice(None, None, 1)
Chris@87 563 w = eval ("w[" + repr(tuple(r)) + "] * ones(ash, float)")
Chris@87 564 n = add.reduce(a * w, axis)
Chris@87 565 d = add.reduce(w, axis, dtype=float)
Chris@87 566 del w, r
Chris@87 567 else:
Chris@87 568 raise ValueError('average: weights wrong shape.')
Chris@87 569 else:
Chris@87 570 if weights is None:
Chris@87 571 n = add.reduce(a, axis)
Chris@87 572 d = umath.add.reduce((~mask), axis=axis, dtype=float)
Chris@87 573 else:
Chris@87 574 w = filled(weights, 0.0)
Chris@87 575 wsh = w.shape
Chris@87 576 if wsh == ():
Chris@87 577 wsh = (1,)
Chris@87 578 if wsh == ash:
Chris@87 579 w = array(w, dtype=float, mask=mask, copy=0)
Chris@87 580 n = add.reduce(a * w, axis)
Chris@87 581 d = add.reduce(w, axis, dtype=float)
Chris@87 582 elif wsh == (ash[axis],):
Chris@87 583 ni = ash[axis]
Chris@87 584 r = [None] * len(ash)
Chris@87 585 r[axis] = slice(None, None, 1)
Chris@87 586 w = eval ("w[" + repr(tuple(r)) + \
Chris@87 587 "] * masked_array(ones(ash, float), mask)")
Chris@87 588 n = add.reduce(a * w, axis)
Chris@87 589 d = add.reduce(w, axis, dtype=float)
Chris@87 590 else:
Chris@87 591 raise ValueError('average: weights wrong shape.')
Chris@87 592 del w
Chris@87 593 if n is masked or d is masked:
Chris@87 594 return masked
Chris@87 595 result = n / d
Chris@87 596 del n
Chris@87 597
Chris@87 598 if isinstance(result, MaskedArray):
Chris@87 599 if ((axis is None) or (axis == 0 and a.ndim == 1)) and \
Chris@87 600 (result.mask is nomask):
Chris@87 601 result = result._data
Chris@87 602 if returned:
Chris@87 603 if not isinstance(d, MaskedArray):
Chris@87 604 d = masked_array(d)
Chris@87 605 if isinstance(d, ndarray) and (not d.shape == result.shape):
Chris@87 606 d = ones(result.shape, dtype=float) * d
Chris@87 607 if returned:
Chris@87 608 return result, d
Chris@87 609 else:
Chris@87 610 return result
Chris@87 611
Chris@87 612
Chris@87 613 def median(a, axis=None, out=None, overwrite_input=False):
Chris@87 614 """
Chris@87 615 Compute the median along the specified axis.
Chris@87 616
Chris@87 617 Returns the median of the array elements.
Chris@87 618
Chris@87 619 Parameters
Chris@87 620 ----------
Chris@87 621 a : array_like
Chris@87 622 Input array or object that can be converted to an array.
Chris@87 623 axis : int, optional
Chris@87 624 Axis along which the medians are computed. The default (None) is
Chris@87 625 to compute the median along a flattened version of the array.
Chris@87 626 out : ndarray, optional
Chris@87 627 Alternative output array in which to place the result. It must
Chris@87 628 have the same shape and buffer length as the expected output
Chris@87 629 but the type will be cast if necessary.
Chris@87 630 overwrite_input : bool, optional
Chris@87 631 If True, then allow use of memory of input array (a) for
Chris@87 632 calculations. The input array will be modified by the call to
Chris@87 633 median. This will save memory when you do not need to preserve
Chris@87 634 the contents of the input array. Treat the input as undefined,
Chris@87 635 but it will probably be fully or partially sorted. Default is
Chris@87 636 False. Note that, if `overwrite_input` is True, and the input
Chris@87 637 is not already an `ndarray`, an error will be raised.
Chris@87 638
Chris@87 639 Returns
Chris@87 640 -------
Chris@87 641 median : ndarray
Chris@87 642 A new array holding the result is returned unless out is
Chris@87 643 specified, in which case a reference to out is returned.
Chris@87 644 Return data-type is `float64` for integers and floats smaller than
Chris@87 645 `float64`, or the input data-type, otherwise.
Chris@87 646
Chris@87 647 See Also
Chris@87 648 --------
Chris@87 649 mean
Chris@87 650
Chris@87 651 Notes
Chris@87 652 -----
Chris@87 653 Given a vector ``V`` with ``N`` non masked values, the median of ``V``
Chris@87 654 is the middle value of a sorted copy of ``V`` (``Vs``) - i.e.
Chris@87 655 ``Vs[(N-1)/2]``, when ``N`` is odd, or ``{Vs[N/2 - 1] + Vs[N/2]}/2``
Chris@87 656 when ``N`` is even.
Chris@87 657
Chris@87 658 Examples
Chris@87 659 --------
Chris@87 660 >>> x = np.ma.array(np.arange(8), mask=[0]*4 + [1]*4)
Chris@87 661 >>> np.ma.extras.median(x)
Chris@87 662 1.5
Chris@87 663
Chris@87 664 >>> x = np.ma.array(np.arange(10).reshape(2, 5), mask=[0]*6 + [1]*4)
Chris@87 665 >>> np.ma.extras.median(x)
Chris@87 666 2.5
Chris@87 667 >>> np.ma.extras.median(x, axis=-1, overwrite_input=True)
Chris@87 668 masked_array(data = [ 2. 5.],
Chris@87 669 mask = False,
Chris@87 670 fill_value = 1e+20)
Chris@87 671
Chris@87 672 """
Chris@87 673 if not hasattr(a, 'mask') or np.count_nonzero(a.mask) == 0:
Chris@87 674 return masked_array(np.median(getattr(a, 'data', a), axis=axis,
Chris@87 675 out=out, overwrite_input=overwrite_input), copy=False)
Chris@87 676 if overwrite_input:
Chris@87 677 if axis is None:
Chris@87 678 asorted = a.ravel()
Chris@87 679 asorted.sort()
Chris@87 680 else:
Chris@87 681 a.sort(axis=axis)
Chris@87 682 asorted = a
Chris@87 683 else:
Chris@87 684 asorted = sort(a, axis=axis)
Chris@87 685 if axis is None:
Chris@87 686 axis = 0
Chris@87 687 elif axis < 0:
Chris@87 688 axis += a.ndim
Chris@87 689
Chris@87 690 counts = asorted.shape[axis] - (asorted.mask).sum(axis=axis)
Chris@87 691 h = counts // 2
Chris@87 692 # create indexing mesh grid for all but reduced axis
Chris@87 693 axes_grid = [np.arange(x) for i, x in enumerate(asorted.shape)
Chris@87 694 if i != axis]
Chris@87 695 ind = np.meshgrid(*axes_grid, sparse=True, indexing='ij')
Chris@87 696 # insert indices of low and high median
Chris@87 697 ind.insert(axis, h - 1)
Chris@87 698 low = asorted[ind]
Chris@87 699 ind[axis] = h
Chris@87 700 high = asorted[ind]
Chris@87 701 # duplicate high if odd number of elements so mean does nothing
Chris@87 702 odd = counts % 2 == 1
Chris@87 703 if asorted.ndim == 1:
Chris@87 704 if odd:
Chris@87 705 low = high
Chris@87 706 else:
Chris@87 707 low[odd] = high[odd]
Chris@87 708
Chris@87 709 if np.issubdtype(asorted.dtype, np.inexact):
Chris@87 710 # avoid inf / x = masked
Chris@87 711 s = np.ma.sum([low, high], axis=0, out=out)
Chris@87 712 np.true_divide(s.data, 2., casting='unsafe', out=s.data)
Chris@87 713 else:
Chris@87 714 s = np.ma.mean([low, high], axis=0, out=out)
Chris@87 715 return s
Chris@87 716
Chris@87 717
Chris@87 718 #..............................................................................
Chris@87 719 def compress_rowcols(x, axis=None):
Chris@87 720 """
Chris@87 721 Suppress the rows and/or columns of a 2-D array that contain
Chris@87 722 masked values.
Chris@87 723
Chris@87 724 The suppression behavior is selected with the `axis` parameter.
Chris@87 725
Chris@87 726 - If axis is None, both rows and columns are suppressed.
Chris@87 727 - If axis is 0, only rows are suppressed.
Chris@87 728 - If axis is 1 or -1, only columns are suppressed.
Chris@87 729
Chris@87 730 Parameters
Chris@87 731 ----------
Chris@87 732 axis : int, optional
Chris@87 733 Axis along which to perform the operation. Default is None.
Chris@87 734
Chris@87 735 Returns
Chris@87 736 -------
Chris@87 737 compressed_array : ndarray
Chris@87 738 The compressed array.
Chris@87 739
Chris@87 740 Examples
Chris@87 741 --------
Chris@87 742 >>> x = np.ma.array(np.arange(9).reshape(3, 3), mask=[[1, 0, 0],
Chris@87 743 ... [1, 0, 0],
Chris@87 744 ... [0, 0, 0]])
Chris@87 745 >>> x
Chris@87 746 masked_array(data =
Chris@87 747 [[-- 1 2]
Chris@87 748 [-- 4 5]
Chris@87 749 [6 7 8]],
Chris@87 750 mask =
Chris@87 751 [[ True False False]
Chris@87 752 [ True False False]
Chris@87 753 [False False False]],
Chris@87 754 fill_value = 999999)
Chris@87 755
Chris@87 756 >>> np.ma.extras.compress_rowcols(x)
Chris@87 757 array([[7, 8]])
Chris@87 758 >>> np.ma.extras.compress_rowcols(x, 0)
Chris@87 759 array([[6, 7, 8]])
Chris@87 760 >>> np.ma.extras.compress_rowcols(x, 1)
Chris@87 761 array([[1, 2],
Chris@87 762 [4, 5],
Chris@87 763 [7, 8]])
Chris@87 764
Chris@87 765 """
Chris@87 766 x = asarray(x)
Chris@87 767 if x.ndim != 2:
Chris@87 768 raise NotImplementedError("compress2d works for 2D arrays only.")
Chris@87 769 m = getmask(x)
Chris@87 770 # Nothing is masked: return x
Chris@87 771 if m is nomask or not m.any():
Chris@87 772 return x._data
Chris@87 773 # All is masked: return empty
Chris@87 774 if m.all():
Chris@87 775 return nxarray([])
Chris@87 776 # Builds a list of rows/columns indices
Chris@87 777 (idxr, idxc) = (list(range(len(x))), list(range(x.shape[1])))
Chris@87 778 masked = m.nonzero()
Chris@87 779 if not axis:
Chris@87 780 for i in np.unique(masked[0]):
Chris@87 781 idxr.remove(i)
Chris@87 782 if axis in [None, 1, -1]:
Chris@87 783 for j in np.unique(masked[1]):
Chris@87 784 idxc.remove(j)
Chris@87 785 return x._data[idxr][:, idxc]
Chris@87 786
Chris@87 787 def compress_rows(a):
Chris@87 788 """
Chris@87 789 Suppress whole rows of a 2-D array that contain masked values.
Chris@87 790
Chris@87 791 This is equivalent to ``np.ma.extras.compress_rowcols(a, 0)``, see
Chris@87 792 `extras.compress_rowcols` for details.
Chris@87 793
Chris@87 794 See Also
Chris@87 795 --------
Chris@87 796 extras.compress_rowcols
Chris@87 797
Chris@87 798 """
Chris@87 799 return compress_rowcols(a, 0)
Chris@87 800
Chris@87 801 def compress_cols(a):
Chris@87 802 """
Chris@87 803 Suppress whole columns of a 2-D array that contain masked values.
Chris@87 804
Chris@87 805 This is equivalent to ``np.ma.extras.compress_rowcols(a, 1)``, see
Chris@87 806 `extras.compress_rowcols` for details.
Chris@87 807
Chris@87 808 See Also
Chris@87 809 --------
Chris@87 810 extras.compress_rowcols
Chris@87 811
Chris@87 812 """
Chris@87 813 return compress_rowcols(a, 1)
Chris@87 814
Chris@87 815 def mask_rowcols(a, axis=None):
Chris@87 816 """
Chris@87 817 Mask rows and/or columns of a 2D array that contain masked values.
Chris@87 818
Chris@87 819 Mask whole rows and/or columns of a 2D array that contain
Chris@87 820 masked values. The masking behavior is selected using the
Chris@87 821 `axis` parameter.
Chris@87 822
Chris@87 823 - If `axis` is None, rows *and* columns are masked.
Chris@87 824 - If `axis` is 0, only rows are masked.
Chris@87 825 - If `axis` is 1 or -1, only columns are masked.
Chris@87 826
Chris@87 827 Parameters
Chris@87 828 ----------
Chris@87 829 a : array_like, MaskedArray
Chris@87 830 The array to mask. If not a MaskedArray instance (or if no array
Chris@87 831 elements are masked). The result is a MaskedArray with `mask` set
Chris@87 832 to `nomask` (False). Must be a 2D array.
Chris@87 833 axis : int, optional
Chris@87 834 Axis along which to perform the operation. If None, applies to a
Chris@87 835 flattened version of the array.
Chris@87 836
Chris@87 837 Returns
Chris@87 838 -------
Chris@87 839 a : MaskedArray
Chris@87 840 A modified version of the input array, masked depending on the value
Chris@87 841 of the `axis` parameter.
Chris@87 842
Chris@87 843 Raises
Chris@87 844 ------
Chris@87 845 NotImplementedError
Chris@87 846 If input array `a` is not 2D.
Chris@87 847
Chris@87 848 See Also
Chris@87 849 --------
Chris@87 850 mask_rows : Mask rows of a 2D array that contain masked values.
Chris@87 851 mask_cols : Mask cols of a 2D array that contain masked values.
Chris@87 852 masked_where : Mask where a condition is met.
Chris@87 853
Chris@87 854 Notes
Chris@87 855 -----
Chris@87 856 The input array's mask is modified by this function.
Chris@87 857
Chris@87 858 Examples
Chris@87 859 --------
Chris@87 860 >>> import numpy.ma as ma
Chris@87 861 >>> a = np.zeros((3, 3), dtype=np.int)
Chris@87 862 >>> a[1, 1] = 1
Chris@87 863 >>> a
Chris@87 864 array([[0, 0, 0],
Chris@87 865 [0, 1, 0],
Chris@87 866 [0, 0, 0]])
Chris@87 867 >>> a = ma.masked_equal(a, 1)
Chris@87 868 >>> a
Chris@87 869 masked_array(data =
Chris@87 870 [[0 0 0]
Chris@87 871 [0 -- 0]
Chris@87 872 [0 0 0]],
Chris@87 873 mask =
Chris@87 874 [[False False False]
Chris@87 875 [False True False]
Chris@87 876 [False False False]],
Chris@87 877 fill_value=999999)
Chris@87 878 >>> ma.mask_rowcols(a)
Chris@87 879 masked_array(data =
Chris@87 880 [[0 -- 0]
Chris@87 881 [-- -- --]
Chris@87 882 [0 -- 0]],
Chris@87 883 mask =
Chris@87 884 [[False True False]
Chris@87 885 [ True True True]
Chris@87 886 [False True False]],
Chris@87 887 fill_value=999999)
Chris@87 888
Chris@87 889 """
Chris@87 890 a = array(a, subok=False)
Chris@87 891 if a.ndim != 2:
Chris@87 892 raise NotImplementedError("mask_rowcols works for 2D arrays only.")
Chris@87 893 m = getmask(a)
Chris@87 894 # Nothing is masked: return a
Chris@87 895 if m is nomask or not m.any():
Chris@87 896 return a
Chris@87 897 maskedval = m.nonzero()
Chris@87 898 a._mask = a._mask.copy()
Chris@87 899 if not axis:
Chris@87 900 a[np.unique(maskedval[0])] = masked
Chris@87 901 if axis in [None, 1, -1]:
Chris@87 902 a[:, np.unique(maskedval[1])] = masked
Chris@87 903 return a
Chris@87 904
Chris@87 905 def mask_rows(a, axis=None):
Chris@87 906 """
Chris@87 907 Mask rows of a 2D array that contain masked values.
Chris@87 908
Chris@87 909 This function is a shortcut to ``mask_rowcols`` with `axis` equal to 0.
Chris@87 910
Chris@87 911 See Also
Chris@87 912 --------
Chris@87 913 mask_rowcols : Mask rows and/or columns of a 2D array.
Chris@87 914 masked_where : Mask where a condition is met.
Chris@87 915
Chris@87 916 Examples
Chris@87 917 --------
Chris@87 918 >>> import numpy.ma as ma
Chris@87 919 >>> a = np.zeros((3, 3), dtype=np.int)
Chris@87 920 >>> a[1, 1] = 1
Chris@87 921 >>> a
Chris@87 922 array([[0, 0, 0],
Chris@87 923 [0, 1, 0],
Chris@87 924 [0, 0, 0]])
Chris@87 925 >>> a = ma.masked_equal(a, 1)
Chris@87 926 >>> a
Chris@87 927 masked_array(data =
Chris@87 928 [[0 0 0]
Chris@87 929 [0 -- 0]
Chris@87 930 [0 0 0]],
Chris@87 931 mask =
Chris@87 932 [[False False False]
Chris@87 933 [False True False]
Chris@87 934 [False False False]],
Chris@87 935 fill_value=999999)
Chris@87 936 >>> ma.mask_rows(a)
Chris@87 937 masked_array(data =
Chris@87 938 [[0 0 0]
Chris@87 939 [-- -- --]
Chris@87 940 [0 0 0]],
Chris@87 941 mask =
Chris@87 942 [[False False False]
Chris@87 943 [ True True True]
Chris@87 944 [False False False]],
Chris@87 945 fill_value=999999)
Chris@87 946
Chris@87 947 """
Chris@87 948 return mask_rowcols(a, 0)
Chris@87 949
Chris@87 950 def mask_cols(a, axis=None):
Chris@87 951 """
Chris@87 952 Mask columns of a 2D array that contain masked values.
Chris@87 953
Chris@87 954 This function is a shortcut to ``mask_rowcols`` with `axis` equal to 1.
Chris@87 955
Chris@87 956 See Also
Chris@87 957 --------
Chris@87 958 mask_rowcols : Mask rows and/or columns of a 2D array.
Chris@87 959 masked_where : Mask where a condition is met.
Chris@87 960
Chris@87 961 Examples
Chris@87 962 --------
Chris@87 963 >>> import numpy.ma as ma
Chris@87 964 >>> a = np.zeros((3, 3), dtype=np.int)
Chris@87 965 >>> a[1, 1] = 1
Chris@87 966 >>> a
Chris@87 967 array([[0, 0, 0],
Chris@87 968 [0, 1, 0],
Chris@87 969 [0, 0, 0]])
Chris@87 970 >>> a = ma.masked_equal(a, 1)
Chris@87 971 >>> a
Chris@87 972 masked_array(data =
Chris@87 973 [[0 0 0]
Chris@87 974 [0 -- 0]
Chris@87 975 [0 0 0]],
Chris@87 976 mask =
Chris@87 977 [[False False False]
Chris@87 978 [False True False]
Chris@87 979 [False False False]],
Chris@87 980 fill_value=999999)
Chris@87 981 >>> ma.mask_cols(a)
Chris@87 982 masked_array(data =
Chris@87 983 [[0 -- 0]
Chris@87 984 [0 -- 0]
Chris@87 985 [0 -- 0]],
Chris@87 986 mask =
Chris@87 987 [[False True False]
Chris@87 988 [False True False]
Chris@87 989 [False True False]],
Chris@87 990 fill_value=999999)
Chris@87 991
Chris@87 992 """
Chris@87 993 return mask_rowcols(a, 1)
Chris@87 994
Chris@87 995
Chris@87 996 def dot(a, b, strict=False):
Chris@87 997 """
Chris@87 998 Return the dot product of two arrays.
Chris@87 999
Chris@87 1000 .. note::
Chris@87 1001 Works only with 2-D arrays at the moment.
Chris@87 1002
Chris@87 1003 This function is the equivalent of `numpy.dot` that takes masked values
Chris@87 1004 into account, see `numpy.dot` for details.
Chris@87 1005
Chris@87 1006 Parameters
Chris@87 1007 ----------
Chris@87 1008 a, b : ndarray
Chris@87 1009 Inputs arrays.
Chris@87 1010 strict : bool, optional
Chris@87 1011 Whether masked data are propagated (True) or set to 0 (False) for the
Chris@87 1012 computation. Default is False.
Chris@87 1013 Propagating the mask means that if a masked value appears in a row or
Chris@87 1014 column, the whole row or column is considered masked.
Chris@87 1015
Chris@87 1016 See Also
Chris@87 1017 --------
Chris@87 1018 numpy.dot : Equivalent function for ndarrays.
Chris@87 1019
Chris@87 1020 Examples
Chris@87 1021 --------
Chris@87 1022 >>> a = ma.array([[1, 2, 3], [4, 5, 6]], mask=[[1, 0, 0], [0, 0, 0]])
Chris@87 1023 >>> b = ma.array([[1, 2], [3, 4], [5, 6]], mask=[[1, 0], [0, 0], [0, 0]])
Chris@87 1024 >>> np.ma.dot(a, b)
Chris@87 1025 masked_array(data =
Chris@87 1026 [[21 26]
Chris@87 1027 [45 64]],
Chris@87 1028 mask =
Chris@87 1029 [[False False]
Chris@87 1030 [False False]],
Chris@87 1031 fill_value = 999999)
Chris@87 1032 >>> np.ma.dot(a, b, strict=True)
Chris@87 1033 masked_array(data =
Chris@87 1034 [[-- --]
Chris@87 1035 [-- 64]],
Chris@87 1036 mask =
Chris@87 1037 [[ True True]
Chris@87 1038 [ True False]],
Chris@87 1039 fill_value = 999999)
Chris@87 1040
Chris@87 1041 """
Chris@87 1042 #!!!: Works only with 2D arrays. There should be a way to get it to run with higher dimension
Chris@87 1043 if strict and (a.ndim == 2) and (b.ndim == 2):
Chris@87 1044 a = mask_rows(a)
Chris@87 1045 b = mask_cols(b)
Chris@87 1046 #
Chris@87 1047 d = np.dot(filled(a, 0), filled(b, 0))
Chris@87 1048 #
Chris@87 1049 am = (~getmaskarray(a))
Chris@87 1050 bm = (~getmaskarray(b))
Chris@87 1051 m = ~np.dot(am, bm)
Chris@87 1052 return masked_array(d, mask=m)
Chris@87 1053
Chris@87 1054 #####--------------------------------------------------------------------------
Chris@87 1055 #---- --- arraysetops ---
Chris@87 1056 #####--------------------------------------------------------------------------
Chris@87 1057
Chris@87 1058 def ediff1d(arr, to_end=None, to_begin=None):
Chris@87 1059 """
Chris@87 1060 Compute the differences between consecutive elements of an array.
Chris@87 1061
Chris@87 1062 This function is the equivalent of `numpy.ediff1d` that takes masked
Chris@87 1063 values into account, see `numpy.ediff1d` for details.
Chris@87 1064
Chris@87 1065 See Also
Chris@87 1066 --------
Chris@87 1067 numpy.ediff1d : Equivalent function for ndarrays.
Chris@87 1068
Chris@87 1069 """
Chris@87 1070 arr = ma.asanyarray(arr).flat
Chris@87 1071 ed = arr[1:] - arr[:-1]
Chris@87 1072 arrays = [ed]
Chris@87 1073 #
Chris@87 1074 if to_begin is not None:
Chris@87 1075 arrays.insert(0, to_begin)
Chris@87 1076 if to_end is not None:
Chris@87 1077 arrays.append(to_end)
Chris@87 1078 #
Chris@87 1079 if len(arrays) != 1:
Chris@87 1080 # We'll save ourselves a copy of a potentially large array in the common
Chris@87 1081 # case where neither to_begin or to_end was given.
Chris@87 1082 ed = hstack(arrays)
Chris@87 1083 #
Chris@87 1084 return ed
Chris@87 1085
Chris@87 1086
Chris@87 1087 def unique(ar1, return_index=False, return_inverse=False):
Chris@87 1088 """
Chris@87 1089 Finds the unique elements of an array.
Chris@87 1090
Chris@87 1091 Masked values are considered the same element (masked). The output array
Chris@87 1092 is always a masked array. See `numpy.unique` for more details.
Chris@87 1093
Chris@87 1094 See Also
Chris@87 1095 --------
Chris@87 1096 numpy.unique : Equivalent function for ndarrays.
Chris@87 1097
Chris@87 1098 """
Chris@87 1099 output = np.unique(ar1,
Chris@87 1100 return_index=return_index,
Chris@87 1101 return_inverse=return_inverse)
Chris@87 1102 if isinstance(output, tuple):
Chris@87 1103 output = list(output)
Chris@87 1104 output[0] = output[0].view(MaskedArray)
Chris@87 1105 output = tuple(output)
Chris@87 1106 else:
Chris@87 1107 output = output.view(MaskedArray)
Chris@87 1108 return output
Chris@87 1109
Chris@87 1110
Chris@87 1111 def intersect1d(ar1, ar2, assume_unique=False):
Chris@87 1112 """
Chris@87 1113 Returns the unique elements common to both arrays.
Chris@87 1114
Chris@87 1115 Masked values are considered equal one to the other.
Chris@87 1116 The output is always a masked array.
Chris@87 1117
Chris@87 1118 See `numpy.intersect1d` for more details.
Chris@87 1119
Chris@87 1120 See Also
Chris@87 1121 --------
Chris@87 1122 numpy.intersect1d : Equivalent function for ndarrays.
Chris@87 1123
Chris@87 1124 Examples
Chris@87 1125 --------
Chris@87 1126 >>> x = array([1, 3, 3, 3], mask=[0, 0, 0, 1])
Chris@87 1127 >>> y = array([3, 1, 1, 1], mask=[0, 0, 0, 1])
Chris@87 1128 >>> intersect1d(x, y)
Chris@87 1129 masked_array(data = [1 3 --],
Chris@87 1130 mask = [False False True],
Chris@87 1131 fill_value = 999999)
Chris@87 1132
Chris@87 1133 """
Chris@87 1134 if assume_unique:
Chris@87 1135 aux = ma.concatenate((ar1, ar2))
Chris@87 1136 else:
Chris@87 1137 # Might be faster than unique( intersect1d( ar1, ar2 ) )?
Chris@87 1138 aux = ma.concatenate((unique(ar1), unique(ar2)))
Chris@87 1139 aux.sort()
Chris@87 1140 return aux[:-1][aux[1:] == aux[:-1]]
Chris@87 1141
Chris@87 1142
Chris@87 1143 def setxor1d(ar1, ar2, assume_unique=False):
Chris@87 1144 """
Chris@87 1145 Set exclusive-or of 1-D arrays with unique elements.
Chris@87 1146
Chris@87 1147 The output is always a masked array. See `numpy.setxor1d` for more details.
Chris@87 1148
Chris@87 1149 See Also
Chris@87 1150 --------
Chris@87 1151 numpy.setxor1d : Equivalent function for ndarrays.
Chris@87 1152
Chris@87 1153 """
Chris@87 1154 if not assume_unique:
Chris@87 1155 ar1 = unique(ar1)
Chris@87 1156 ar2 = unique(ar2)
Chris@87 1157
Chris@87 1158 aux = ma.concatenate((ar1, ar2))
Chris@87 1159 if aux.size == 0:
Chris@87 1160 return aux
Chris@87 1161 aux.sort()
Chris@87 1162 auxf = aux.filled()
Chris@87 1163 # flag = ediff1d( aux, to_end = 1, to_begin = 1 ) == 0
Chris@87 1164 flag = ma.concatenate(([True], (auxf[1:] != auxf[:-1]), [True]))
Chris@87 1165 # flag2 = ediff1d( flag ) == 0
Chris@87 1166 flag2 = (flag[1:] == flag[:-1])
Chris@87 1167 return aux[flag2]
Chris@87 1168
Chris@87 1169 def in1d(ar1, ar2, assume_unique=False, invert=False):
Chris@87 1170 """
Chris@87 1171 Test whether each element of an array is also present in a second
Chris@87 1172 array.
Chris@87 1173
Chris@87 1174 The output is always a masked array. See `numpy.in1d` for more details.
Chris@87 1175
Chris@87 1176 See Also
Chris@87 1177 --------
Chris@87 1178 numpy.in1d : Equivalent function for ndarrays.
Chris@87 1179
Chris@87 1180 Notes
Chris@87 1181 -----
Chris@87 1182 .. versionadded:: 1.4.0
Chris@87 1183
Chris@87 1184 """
Chris@87 1185 if not assume_unique:
Chris@87 1186 ar1, rev_idx = unique(ar1, return_inverse=True)
Chris@87 1187 ar2 = unique(ar2)
Chris@87 1188
Chris@87 1189 ar = ma.concatenate((ar1, ar2))
Chris@87 1190 # We need this to be a stable sort, so always use 'mergesort'
Chris@87 1191 # here. The values from the first array should always come before
Chris@87 1192 # the values from the second array.
Chris@87 1193 order = ar.argsort(kind='mergesort')
Chris@87 1194 sar = ar[order]
Chris@87 1195 if invert:
Chris@87 1196 bool_ar = (sar[1:] != sar[:-1])
Chris@87 1197 else:
Chris@87 1198 bool_ar = (sar[1:] == sar[:-1])
Chris@87 1199 flag = ma.concatenate((bool_ar, [invert]))
Chris@87 1200 indx = order.argsort(kind='mergesort')[:len(ar1)]
Chris@87 1201
Chris@87 1202 if assume_unique:
Chris@87 1203 return flag[indx]
Chris@87 1204 else:
Chris@87 1205 return flag[indx][rev_idx]
Chris@87 1206
Chris@87 1207
Chris@87 1208 def union1d(ar1, ar2):
Chris@87 1209 """
Chris@87 1210 Union of two arrays.
Chris@87 1211
Chris@87 1212 The output is always a masked array. See `numpy.union1d` for more details.
Chris@87 1213
Chris@87 1214 See also
Chris@87 1215 --------
Chris@87 1216 numpy.union1d : Equivalent function for ndarrays.
Chris@87 1217
Chris@87 1218 """
Chris@87 1219 return unique(ma.concatenate((ar1, ar2)))
Chris@87 1220
Chris@87 1221
Chris@87 1222 def setdiff1d(ar1, ar2, assume_unique=False):
Chris@87 1223 """
Chris@87 1224 Set difference of 1D arrays with unique elements.
Chris@87 1225
Chris@87 1226 The output is always a masked array. See `numpy.setdiff1d` for more
Chris@87 1227 details.
Chris@87 1228
Chris@87 1229 See Also
Chris@87 1230 --------
Chris@87 1231 numpy.setdiff1d : Equivalent function for ndarrays.
Chris@87 1232
Chris@87 1233 Examples
Chris@87 1234 --------
Chris@87 1235 >>> x = np.ma.array([1, 2, 3, 4], mask=[0, 1, 0, 1])
Chris@87 1236 >>> np.ma.extras.setdiff1d(x, [1, 2])
Chris@87 1237 masked_array(data = [3 --],
Chris@87 1238 mask = [False True],
Chris@87 1239 fill_value = 999999)
Chris@87 1240
Chris@87 1241 """
Chris@87 1242 if not assume_unique:
Chris@87 1243 ar1 = unique(ar1)
Chris@87 1244 ar2 = unique(ar2)
Chris@87 1245 aux = in1d(ar1, ar2, assume_unique=True)
Chris@87 1246 if aux.size == 0:
Chris@87 1247 return aux
Chris@87 1248 else:
Chris@87 1249 return ma.asarray(ar1)[aux == 0]
Chris@87 1250
Chris@87 1251
Chris@87 1252 #####--------------------------------------------------------------------------
Chris@87 1253 #---- --- Covariance ---
Chris@87 1254 #####--------------------------------------------------------------------------
Chris@87 1255
Chris@87 1256
Chris@87 1257
Chris@87 1258
Chris@87 1259 def _covhelper(x, y=None, rowvar=True, allow_masked=True):
Chris@87 1260 """
Chris@87 1261 Private function for the computation of covariance and correlation
Chris@87 1262 coefficients.
Chris@87 1263
Chris@87 1264 """
Chris@87 1265 x = ma.array(x, ndmin=2, copy=True, dtype=float)
Chris@87 1266 xmask = ma.getmaskarray(x)
Chris@87 1267 # Quick exit if we can't process masked data
Chris@87 1268 if not allow_masked and xmask.any():
Chris@87 1269 raise ValueError("Cannot process masked data...")
Chris@87 1270 #
Chris@87 1271 if x.shape[0] == 1:
Chris@87 1272 rowvar = True
Chris@87 1273 # Make sure that rowvar is either 0 or 1
Chris@87 1274 rowvar = int(bool(rowvar))
Chris@87 1275 axis = 1 - rowvar
Chris@87 1276 if rowvar:
Chris@87 1277 tup = (slice(None), None)
Chris@87 1278 else:
Chris@87 1279 tup = (None, slice(None))
Chris@87 1280 #
Chris@87 1281 if y is None:
Chris@87 1282 xnotmask = np.logical_not(xmask).astype(int)
Chris@87 1283 else:
Chris@87 1284 y = array(y, copy=False, ndmin=2, dtype=float)
Chris@87 1285 ymask = ma.getmaskarray(y)
Chris@87 1286 if not allow_masked and ymask.any():
Chris@87 1287 raise ValueError("Cannot process masked data...")
Chris@87 1288 if xmask.any() or ymask.any():
Chris@87 1289 if y.shape == x.shape:
Chris@87 1290 # Define some common mask
Chris@87 1291 common_mask = np.logical_or(xmask, ymask)
Chris@87 1292 if common_mask is not nomask:
Chris@87 1293 x.unshare_mask()
Chris@87 1294 y.unshare_mask()
Chris@87 1295 xmask = x._mask = y._mask = ymask = common_mask
Chris@87 1296 x = ma.concatenate((x, y), axis)
Chris@87 1297 xnotmask = np.logical_not(np.concatenate((xmask, ymask), axis)).astype(int)
Chris@87 1298 x -= x.mean(axis=rowvar)[tup]
Chris@87 1299 return (x, xnotmask, rowvar)
Chris@87 1300
Chris@87 1301
Chris@87 1302 def cov(x, y=None, rowvar=True, bias=False, allow_masked=True, ddof=None):
Chris@87 1303 """
Chris@87 1304 Estimate the covariance matrix.
Chris@87 1305
Chris@87 1306 Except for the handling of missing data this function does the same as
Chris@87 1307 `numpy.cov`. For more details and examples, see `numpy.cov`.
Chris@87 1308
Chris@87 1309 By default, masked values are recognized as such. If `x` and `y` have the
Chris@87 1310 same shape, a common mask is allocated: if ``x[i,j]`` is masked, then
Chris@87 1311 ``y[i,j]`` will also be masked.
Chris@87 1312 Setting `allow_masked` to False will raise an exception if values are
Chris@87 1313 missing in either of the input arrays.
Chris@87 1314
Chris@87 1315 Parameters
Chris@87 1316 ----------
Chris@87 1317 x : array_like
Chris@87 1318 A 1-D or 2-D array containing multiple variables and observations.
Chris@87 1319 Each row of `x` represents a variable, and each column a single
Chris@87 1320 observation of all those variables. Also see `rowvar` below.
Chris@87 1321 y : array_like, optional
Chris@87 1322 An additional set of variables and observations. `y` has the same
Chris@87 1323 form as `x`.
Chris@87 1324 rowvar : bool, optional
Chris@87 1325 If `rowvar` is True (default), then each row represents a
Chris@87 1326 variable, with observations in the columns. Otherwise, the relationship
Chris@87 1327 is transposed: each column represents a variable, while the rows
Chris@87 1328 contain observations.
Chris@87 1329 bias : bool, optional
Chris@87 1330 Default normalization (False) is by ``(N-1)``, where ``N`` is the
Chris@87 1331 number of observations given (unbiased estimate). If `bias` is True,
Chris@87 1332 then normalization is by ``N``. This keyword can be overridden by
Chris@87 1333 the keyword ``ddof`` in numpy versions >= 1.5.
Chris@87 1334 allow_masked : bool, optional
Chris@87 1335 If True, masked values are propagated pair-wise: if a value is masked
Chris@87 1336 in `x`, the corresponding value is masked in `y`.
Chris@87 1337 If False, raises a `ValueError` exception when some values are missing.
Chris@87 1338 ddof : {None, int}, optional
Chris@87 1339 .. versionadded:: 1.5
Chris@87 1340 If not ``None`` normalization is by ``(N - ddof)``, where ``N`` is
Chris@87 1341 the number of observations; this overrides the value implied by
Chris@87 1342 ``bias``. The default value is ``None``.
Chris@87 1343
Chris@87 1344
Chris@87 1345 Raises
Chris@87 1346 ------
Chris@87 1347 ValueError
Chris@87 1348 Raised if some values are missing and `allow_masked` is False.
Chris@87 1349
Chris@87 1350 See Also
Chris@87 1351 --------
Chris@87 1352 numpy.cov
Chris@87 1353
Chris@87 1354 """
Chris@87 1355 # Check inputs
Chris@87 1356 if ddof is not None and ddof != int(ddof):
Chris@87 1357 raise ValueError("ddof must be an integer")
Chris@87 1358 # Set up ddof
Chris@87 1359 if ddof is None:
Chris@87 1360 if bias:
Chris@87 1361 ddof = 0
Chris@87 1362 else:
Chris@87 1363 ddof = 1
Chris@87 1364
Chris@87 1365 (x, xnotmask, rowvar) = _covhelper(x, y, rowvar, allow_masked)
Chris@87 1366 if not rowvar:
Chris@87 1367 fact = np.dot(xnotmask.T, xnotmask) * 1. - ddof
Chris@87 1368 result = (dot(x.T, x.conj(), strict=False) / fact).squeeze()
Chris@87 1369 else:
Chris@87 1370 fact = np.dot(xnotmask, xnotmask.T) * 1. - ddof
Chris@87 1371 result = (dot(x, x.T.conj(), strict=False) / fact).squeeze()
Chris@87 1372 return result
Chris@87 1373
Chris@87 1374
Chris@87 1375 def corrcoef(x, y=None, rowvar=True, bias=False, allow_masked=True, ddof=None):
Chris@87 1376 """
Chris@87 1377 Return correlation coefficients of the input array.
Chris@87 1378
Chris@87 1379 Except for the handling of missing data this function does the same as
Chris@87 1380 `numpy.corrcoef`. For more details and examples, see `numpy.corrcoef`.
Chris@87 1381
Chris@87 1382 Parameters
Chris@87 1383 ----------
Chris@87 1384 x : array_like
Chris@87 1385 A 1-D or 2-D array containing multiple variables and observations.
Chris@87 1386 Each row of `x` represents a variable, and each column a single
Chris@87 1387 observation of all those variables. Also see `rowvar` below.
Chris@87 1388 y : array_like, optional
Chris@87 1389 An additional set of variables and observations. `y` has the same
Chris@87 1390 shape as `x`.
Chris@87 1391 rowvar : bool, optional
Chris@87 1392 If `rowvar` is True (default), then each row represents a
Chris@87 1393 variable, with observations in the columns. Otherwise, the relationship
Chris@87 1394 is transposed: each column represents a variable, while the rows
Chris@87 1395 contain observations.
Chris@87 1396 bias : bool, optional
Chris@87 1397 Default normalization (False) is by ``(N-1)``, where ``N`` is the
Chris@87 1398 number of observations given (unbiased estimate). If `bias` is 1,
Chris@87 1399 then normalization is by ``N``. This keyword can be overridden by
Chris@87 1400 the keyword ``ddof`` in numpy versions >= 1.5.
Chris@87 1401 allow_masked : bool, optional
Chris@87 1402 If True, masked values are propagated pair-wise: if a value is masked
Chris@87 1403 in `x`, the corresponding value is masked in `y`.
Chris@87 1404 If False, raises an exception.
Chris@87 1405 ddof : {None, int}, optional
Chris@87 1406 .. versionadded:: 1.5
Chris@87 1407 If not ``None`` normalization is by ``(N - ddof)``, where ``N`` is
Chris@87 1408 the number of observations; this overrides the value implied by
Chris@87 1409 ``bias``. The default value is ``None``.
Chris@87 1410
Chris@87 1411 See Also
Chris@87 1412 --------
Chris@87 1413 numpy.corrcoef : Equivalent function in top-level NumPy module.
Chris@87 1414 cov : Estimate the covariance matrix.
Chris@87 1415
Chris@87 1416 """
Chris@87 1417 # Check inputs
Chris@87 1418 if ddof is not None and ddof != int(ddof):
Chris@87 1419 raise ValueError("ddof must be an integer")
Chris@87 1420 # Set up ddof
Chris@87 1421 if ddof is None:
Chris@87 1422 if bias:
Chris@87 1423 ddof = 0
Chris@87 1424 else:
Chris@87 1425 ddof = 1
Chris@87 1426
Chris@87 1427 # Get the data
Chris@87 1428 (x, xnotmask, rowvar) = _covhelper(x, y, rowvar, allow_masked)
Chris@87 1429 # Compute the covariance matrix
Chris@87 1430 if not rowvar:
Chris@87 1431 fact = np.dot(xnotmask.T, xnotmask) * 1. - ddof
Chris@87 1432 c = (dot(x.T, x.conj(), strict=False) / fact).squeeze()
Chris@87 1433 else:
Chris@87 1434 fact = np.dot(xnotmask, xnotmask.T) * 1. - ddof
Chris@87 1435 c = (dot(x, x.T.conj(), strict=False) / fact).squeeze()
Chris@87 1436 # Check whether we have a scalar
Chris@87 1437 try:
Chris@87 1438 diag = ma.diagonal(c)
Chris@87 1439 except ValueError:
Chris@87 1440 return 1
Chris@87 1441 #
Chris@87 1442 if xnotmask.all():
Chris@87 1443 _denom = ma.sqrt(ma.multiply.outer(diag, diag))
Chris@87 1444 else:
Chris@87 1445 _denom = diagflat(diag)
Chris@87 1446 n = x.shape[1 - rowvar]
Chris@87 1447 if rowvar:
Chris@87 1448 for i in range(n - 1):
Chris@87 1449 for j in range(i + 1, n):
Chris@87 1450 _x = mask_cols(vstack((x[i], x[j]))).var(axis=1, ddof=ddof)
Chris@87 1451 _denom[i, j] = _denom[j, i] = ma.sqrt(ma.multiply.reduce(_x))
Chris@87 1452 else:
Chris@87 1453 for i in range(n - 1):
Chris@87 1454 for j in range(i + 1, n):
Chris@87 1455 _x = mask_cols(
Chris@87 1456 vstack((x[:, i], x[:, j]))).var(axis=1, ddof=ddof)
Chris@87 1457 _denom[i, j] = _denom[j, i] = ma.sqrt(ma.multiply.reduce(_x))
Chris@87 1458 return c / _denom
Chris@87 1459
Chris@87 1460 #####--------------------------------------------------------------------------
Chris@87 1461 #---- --- Concatenation helpers ---
Chris@87 1462 #####--------------------------------------------------------------------------
Chris@87 1463
Chris@87 1464 class MAxisConcatenator(AxisConcatenator):
Chris@87 1465 """
Chris@87 1466 Translate slice objects to concatenation along an axis.
Chris@87 1467
Chris@87 1468 For documentation on usage, see `mr_class`.
Chris@87 1469
Chris@87 1470 See Also
Chris@87 1471 --------
Chris@87 1472 mr_class
Chris@87 1473
Chris@87 1474 """
Chris@87 1475
Chris@87 1476 def __init__(self, axis=0):
Chris@87 1477 AxisConcatenator.__init__(self, axis, matrix=False)
Chris@87 1478
Chris@87 1479 def __getitem__(self, key):
Chris@87 1480 if isinstance(key, str):
Chris@87 1481 raise MAError("Unavailable for masked array.")
Chris@87 1482 if not isinstance(key, tuple):
Chris@87 1483 key = (key,)
Chris@87 1484 objs = []
Chris@87 1485 scalars = []
Chris@87 1486 final_dtypedescr = None
Chris@87 1487 for k in range(len(key)):
Chris@87 1488 scalar = False
Chris@87 1489 if isinstance(key[k], slice):
Chris@87 1490 step = key[k].step
Chris@87 1491 start = key[k].start
Chris@87 1492 stop = key[k].stop
Chris@87 1493 if start is None:
Chris@87 1494 start = 0
Chris@87 1495 if step is None:
Chris@87 1496 step = 1
Chris@87 1497 if isinstance(step, complex):
Chris@87 1498 size = int(abs(step))
Chris@87 1499 newobj = np.linspace(start, stop, num=size)
Chris@87 1500 else:
Chris@87 1501 newobj = np.arange(start, stop, step)
Chris@87 1502 elif isinstance(key[k], str):
Chris@87 1503 if (key[k] in 'rc'):
Chris@87 1504 self.matrix = True
Chris@87 1505 self.col = (key[k] == 'c')
Chris@87 1506 continue
Chris@87 1507 try:
Chris@87 1508 self.axis = int(key[k])
Chris@87 1509 continue
Chris@87 1510 except (ValueError, TypeError):
Chris@87 1511 raise ValueError("Unknown special directive")
Chris@87 1512 elif type(key[k]) in np.ScalarType:
Chris@87 1513 newobj = asarray([key[k]])
Chris@87 1514 scalars.append(k)
Chris@87 1515 scalar = True
Chris@87 1516 else:
Chris@87 1517 newobj = key[k]
Chris@87 1518 objs.append(newobj)
Chris@87 1519 if isinstance(newobj, ndarray) and not scalar:
Chris@87 1520 if final_dtypedescr is None:
Chris@87 1521 final_dtypedescr = newobj.dtype
Chris@87 1522 elif newobj.dtype > final_dtypedescr:
Chris@87 1523 final_dtypedescr = newobj.dtype
Chris@87 1524 if final_dtypedescr is not None:
Chris@87 1525 for k in scalars:
Chris@87 1526 objs[k] = objs[k].astype(final_dtypedescr)
Chris@87 1527 res = concatenate(tuple(objs), axis=self.axis)
Chris@87 1528 return self._retval(res)
Chris@87 1529
Chris@87 1530 class mr_class(MAxisConcatenator):
Chris@87 1531 """
Chris@87 1532 Translate slice objects to concatenation along the first axis.
Chris@87 1533
Chris@87 1534 This is the masked array version of `lib.index_tricks.RClass`.
Chris@87 1535
Chris@87 1536 See Also
Chris@87 1537 --------
Chris@87 1538 lib.index_tricks.RClass
Chris@87 1539
Chris@87 1540 Examples
Chris@87 1541 --------
Chris@87 1542 >>> np.ma.mr_[np.ma.array([1,2,3]), 0, 0, np.ma.array([4,5,6])]
Chris@87 1543 array([1, 2, 3, 0, 0, 4, 5, 6])
Chris@87 1544
Chris@87 1545 """
Chris@87 1546 def __init__(self):
Chris@87 1547 MAxisConcatenator.__init__(self, 0)
Chris@87 1548
Chris@87 1549 mr_ = mr_class()
Chris@87 1550
Chris@87 1551 #####--------------------------------------------------------------------------
Chris@87 1552 #---- Find unmasked data ---
Chris@87 1553 #####--------------------------------------------------------------------------
Chris@87 1554
Chris@87 1555 def flatnotmasked_edges(a):
Chris@87 1556 """
Chris@87 1557 Find the indices of the first and last unmasked values.
Chris@87 1558
Chris@87 1559 Expects a 1-D `MaskedArray`, returns None if all values are masked.
Chris@87 1560
Chris@87 1561 Parameters
Chris@87 1562 ----------
Chris@87 1563 arr : array_like
Chris@87 1564 Input 1-D `MaskedArray`
Chris@87 1565
Chris@87 1566 Returns
Chris@87 1567 -------
Chris@87 1568 edges : ndarray or None
Chris@87 1569 The indices of first and last non-masked value in the array.
Chris@87 1570 Returns None if all values are masked.
Chris@87 1571
Chris@87 1572 See Also
Chris@87 1573 --------
Chris@87 1574 flatnotmasked_contiguous, notmasked_contiguous, notmasked_edges,
Chris@87 1575 clump_masked, clump_unmasked
Chris@87 1576
Chris@87 1577 Notes
Chris@87 1578 -----
Chris@87 1579 Only accepts 1-D arrays.
Chris@87 1580
Chris@87 1581 Examples
Chris@87 1582 --------
Chris@87 1583 >>> a = np.ma.arange(10)
Chris@87 1584 >>> flatnotmasked_edges(a)
Chris@87 1585 [0,-1]
Chris@87 1586
Chris@87 1587 >>> mask = (a < 3) | (a > 8) | (a == 5)
Chris@87 1588 >>> a[mask] = np.ma.masked
Chris@87 1589 >>> np.array(a[~a.mask])
Chris@87 1590 array([3, 4, 6, 7, 8])
Chris@87 1591
Chris@87 1592 >>> flatnotmasked_edges(a)
Chris@87 1593 array([3, 8])
Chris@87 1594
Chris@87 1595 >>> a[:] = np.ma.masked
Chris@87 1596 >>> print flatnotmasked_edges(ma)
Chris@87 1597 None
Chris@87 1598
Chris@87 1599 """
Chris@87 1600 m = getmask(a)
Chris@87 1601 if m is nomask or not np.any(m):
Chris@87 1602 return np.array([0, a.size - 1])
Chris@87 1603 unmasked = np.flatnonzero(~m)
Chris@87 1604 if len(unmasked) > 0:
Chris@87 1605 return unmasked[[0, -1]]
Chris@87 1606 else:
Chris@87 1607 return None
Chris@87 1608
Chris@87 1609
Chris@87 1610 def notmasked_edges(a, axis=None):
Chris@87 1611 """
Chris@87 1612 Find the indices of the first and last unmasked values along an axis.
Chris@87 1613
Chris@87 1614 If all values are masked, return None. Otherwise, return a list
Chris@87 1615 of two tuples, corresponding to the indices of the first and last
Chris@87 1616 unmasked values respectively.
Chris@87 1617
Chris@87 1618 Parameters
Chris@87 1619 ----------
Chris@87 1620 a : array_like
Chris@87 1621 The input array.
Chris@87 1622 axis : int, optional
Chris@87 1623 Axis along which to perform the operation.
Chris@87 1624 If None (default), applies to a flattened version of the array.
Chris@87 1625
Chris@87 1626 Returns
Chris@87 1627 -------
Chris@87 1628 edges : ndarray or list
Chris@87 1629 An array of start and end indexes if there are any masked data in
Chris@87 1630 the array. If there are no masked data in the array, `edges` is a
Chris@87 1631 list of the first and last index.
Chris@87 1632
Chris@87 1633 See Also
Chris@87 1634 --------
Chris@87 1635 flatnotmasked_contiguous, flatnotmasked_edges, notmasked_contiguous,
Chris@87 1636 clump_masked, clump_unmasked
Chris@87 1637
Chris@87 1638 Examples
Chris@87 1639 --------
Chris@87 1640 >>> a = np.arange(9).reshape((3, 3))
Chris@87 1641 >>> m = np.zeros_like(a)
Chris@87 1642 >>> m[1:, 1:] = 1
Chris@87 1643
Chris@87 1644 >>> am = np.ma.array(a, mask=m)
Chris@87 1645 >>> np.array(am[~am.mask])
Chris@87 1646 array([0, 1, 2, 3, 6])
Chris@87 1647
Chris@87 1648 >>> np.ma.extras.notmasked_edges(ma)
Chris@87 1649 array([0, 6])
Chris@87 1650
Chris@87 1651 """
Chris@87 1652 a = asarray(a)
Chris@87 1653 if axis is None or a.ndim == 1:
Chris@87 1654 return flatnotmasked_edges(a)
Chris@87 1655 m = getmaskarray(a)
Chris@87 1656 idx = array(np.indices(a.shape), mask=np.asarray([m] * a.ndim))
Chris@87 1657 return [tuple([idx[i].min(axis).compressed() for i in range(a.ndim)]),
Chris@87 1658 tuple([idx[i].max(axis).compressed() for i in range(a.ndim)]), ]
Chris@87 1659
Chris@87 1660
Chris@87 1661 def flatnotmasked_contiguous(a):
Chris@87 1662 """
Chris@87 1663 Find contiguous unmasked data in a masked array along the given axis.
Chris@87 1664
Chris@87 1665 Parameters
Chris@87 1666 ----------
Chris@87 1667 a : narray
Chris@87 1668 The input array.
Chris@87 1669
Chris@87 1670 Returns
Chris@87 1671 -------
Chris@87 1672 slice_list : list
Chris@87 1673 A sorted sequence of slices (start index, end index).
Chris@87 1674
Chris@87 1675 See Also
Chris@87 1676 --------
Chris@87 1677 flatnotmasked_edges, notmasked_contiguous, notmasked_edges,
Chris@87 1678 clump_masked, clump_unmasked
Chris@87 1679
Chris@87 1680 Notes
Chris@87 1681 -----
Chris@87 1682 Only accepts 2-D arrays at most.
Chris@87 1683
Chris@87 1684 Examples
Chris@87 1685 --------
Chris@87 1686 >>> a = np.ma.arange(10)
Chris@87 1687 >>> np.ma.extras.flatnotmasked_contiguous(a)
Chris@87 1688 slice(0, 10, None)
Chris@87 1689
Chris@87 1690 >>> mask = (a < 3) | (a > 8) | (a == 5)
Chris@87 1691 >>> a[mask] = np.ma.masked
Chris@87 1692 >>> np.array(a[~a.mask])
Chris@87 1693 array([3, 4, 6, 7, 8])
Chris@87 1694
Chris@87 1695 >>> np.ma.extras.flatnotmasked_contiguous(a)
Chris@87 1696 [slice(3, 5, None), slice(6, 9, None)]
Chris@87 1697 >>> a[:] = np.ma.masked
Chris@87 1698 >>> print np.ma.extras.flatnotmasked_edges(a)
Chris@87 1699 None
Chris@87 1700
Chris@87 1701 """
Chris@87 1702 m = getmask(a)
Chris@87 1703 if m is nomask:
Chris@87 1704 return slice(0, a.size, None)
Chris@87 1705 i = 0
Chris@87 1706 result = []
Chris@87 1707 for (k, g) in itertools.groupby(m.ravel()):
Chris@87 1708 n = len(list(g))
Chris@87 1709 if not k:
Chris@87 1710 result.append(slice(i, i + n))
Chris@87 1711 i += n
Chris@87 1712 return result or None
Chris@87 1713
Chris@87 1714 def notmasked_contiguous(a, axis=None):
Chris@87 1715 """
Chris@87 1716 Find contiguous unmasked data in a masked array along the given axis.
Chris@87 1717
Chris@87 1718 Parameters
Chris@87 1719 ----------
Chris@87 1720 a : array_like
Chris@87 1721 The input array.
Chris@87 1722 axis : int, optional
Chris@87 1723 Axis along which to perform the operation.
Chris@87 1724 If None (default), applies to a flattened version of the array.
Chris@87 1725
Chris@87 1726 Returns
Chris@87 1727 -------
Chris@87 1728 endpoints : list
Chris@87 1729 A list of slices (start and end indexes) of unmasked indexes
Chris@87 1730 in the array.
Chris@87 1731
Chris@87 1732 See Also
Chris@87 1733 --------
Chris@87 1734 flatnotmasked_edges, flatnotmasked_contiguous, notmasked_edges,
Chris@87 1735 clump_masked, clump_unmasked
Chris@87 1736
Chris@87 1737 Notes
Chris@87 1738 -----
Chris@87 1739 Only accepts 2-D arrays at most.
Chris@87 1740
Chris@87 1741 Examples
Chris@87 1742 --------
Chris@87 1743 >>> a = np.arange(9).reshape((3, 3))
Chris@87 1744 >>> mask = np.zeros_like(a)
Chris@87 1745 >>> mask[1:, 1:] = 1
Chris@87 1746
Chris@87 1747 >>> ma = np.ma.array(a, mask=mask)
Chris@87 1748 >>> np.array(ma[~ma.mask])
Chris@87 1749 array([0, 1, 2, 3, 6])
Chris@87 1750
Chris@87 1751 >>> np.ma.extras.notmasked_contiguous(ma)
Chris@87 1752 [slice(0, 4, None), slice(6, 7, None)]
Chris@87 1753
Chris@87 1754 """
Chris@87 1755 a = asarray(a)
Chris@87 1756 nd = a.ndim
Chris@87 1757 if nd > 2:
Chris@87 1758 raise NotImplementedError("Currently limited to atmost 2D array.")
Chris@87 1759 if axis is None or nd == 1:
Chris@87 1760 return flatnotmasked_contiguous(a)
Chris@87 1761 #
Chris@87 1762 result = []
Chris@87 1763 #
Chris@87 1764 other = (axis + 1) % 2
Chris@87 1765 idx = [0, 0]
Chris@87 1766 idx[axis] = slice(None, None)
Chris@87 1767 #
Chris@87 1768 for i in range(a.shape[other]):
Chris@87 1769 idx[other] = i
Chris@87 1770 result.append(flatnotmasked_contiguous(a[idx]) or None)
Chris@87 1771 return result
Chris@87 1772
Chris@87 1773
Chris@87 1774 def _ezclump(mask):
Chris@87 1775 """
Chris@87 1776 Finds the clumps (groups of data with the same values) for a 1D bool array.
Chris@87 1777
Chris@87 1778 Returns a series of slices.
Chris@87 1779 """
Chris@87 1780 #def clump_masked(a):
Chris@87 1781 if mask.ndim > 1:
Chris@87 1782 mask = mask.ravel()
Chris@87 1783 idx = (mask[1:] ^ mask[:-1]).nonzero()
Chris@87 1784 idx = idx[0] + 1
Chris@87 1785 slices = [slice(left, right)
Chris@87 1786 for (left, right) in zip(itertools.chain([0], idx),
Chris@87 1787 itertools.chain(idx, [len(mask)]),)]
Chris@87 1788 return slices
Chris@87 1789
Chris@87 1790
Chris@87 1791 def clump_unmasked(a):
Chris@87 1792 """
Chris@87 1793 Return list of slices corresponding to the unmasked clumps of a 1-D array.
Chris@87 1794 (A "clump" is defined as a contiguous region of the array).
Chris@87 1795
Chris@87 1796 Parameters
Chris@87 1797 ----------
Chris@87 1798 a : ndarray
Chris@87 1799 A one-dimensional masked array.
Chris@87 1800
Chris@87 1801 Returns
Chris@87 1802 -------
Chris@87 1803 slices : list of slice
Chris@87 1804 The list of slices, one for each continuous region of unmasked
Chris@87 1805 elements in `a`.
Chris@87 1806
Chris@87 1807 Notes
Chris@87 1808 -----
Chris@87 1809 .. versionadded:: 1.4.0
Chris@87 1810
Chris@87 1811 See Also
Chris@87 1812 --------
Chris@87 1813 flatnotmasked_edges, flatnotmasked_contiguous, notmasked_edges,
Chris@87 1814 notmasked_contiguous, clump_masked
Chris@87 1815
Chris@87 1816 Examples
Chris@87 1817 --------
Chris@87 1818 >>> a = np.ma.masked_array(np.arange(10))
Chris@87 1819 >>> a[[0, 1, 2, 6, 8, 9]] = np.ma.masked
Chris@87 1820 >>> np.ma.extras.clump_unmasked(a)
Chris@87 1821 [slice(3, 6, None), slice(7, 8, None)]
Chris@87 1822
Chris@87 1823 """
Chris@87 1824 mask = getattr(a, '_mask', nomask)
Chris@87 1825 if mask is nomask:
Chris@87 1826 return [slice(0, a.size)]
Chris@87 1827 slices = _ezclump(mask)
Chris@87 1828 if a[0] is masked:
Chris@87 1829 result = slices[1::2]
Chris@87 1830 else:
Chris@87 1831 result = slices[::2]
Chris@87 1832 return result
Chris@87 1833
Chris@87 1834
Chris@87 1835 def clump_masked(a):
Chris@87 1836 """
Chris@87 1837 Returns a list of slices corresponding to the masked clumps of a 1-D array.
Chris@87 1838 (A "clump" is defined as a contiguous region of the array).
Chris@87 1839
Chris@87 1840 Parameters
Chris@87 1841 ----------
Chris@87 1842 a : ndarray
Chris@87 1843 A one-dimensional masked array.
Chris@87 1844
Chris@87 1845 Returns
Chris@87 1846 -------
Chris@87 1847 slices : list of slice
Chris@87 1848 The list of slices, one for each continuous region of masked elements
Chris@87 1849 in `a`.
Chris@87 1850
Chris@87 1851 Notes
Chris@87 1852 -----
Chris@87 1853 .. versionadded:: 1.4.0
Chris@87 1854
Chris@87 1855 See Also
Chris@87 1856 --------
Chris@87 1857 flatnotmasked_edges, flatnotmasked_contiguous, notmasked_edges,
Chris@87 1858 notmasked_contiguous, clump_unmasked
Chris@87 1859
Chris@87 1860 Examples
Chris@87 1861 --------
Chris@87 1862 >>> a = np.ma.masked_array(np.arange(10))
Chris@87 1863 >>> a[[0, 1, 2, 6, 8, 9]] = np.ma.masked
Chris@87 1864 >>> np.ma.extras.clump_masked(a)
Chris@87 1865 [slice(0, 3, None), slice(6, 7, None), slice(8, 10, None)]
Chris@87 1866
Chris@87 1867 """
Chris@87 1868 mask = ma.getmask(a)
Chris@87 1869 if mask is nomask:
Chris@87 1870 return []
Chris@87 1871 slices = _ezclump(mask)
Chris@87 1872 if len(slices):
Chris@87 1873 if a[0] is masked:
Chris@87 1874 slices = slices[::2]
Chris@87 1875 else:
Chris@87 1876 slices = slices[1::2]
Chris@87 1877 return slices
Chris@87 1878
Chris@87 1879
Chris@87 1880
Chris@87 1881 #####--------------------------------------------------------------------------
Chris@87 1882 #---- Polynomial fit ---
Chris@87 1883 #####--------------------------------------------------------------------------
Chris@87 1884
Chris@87 1885 def vander(x, n=None):
Chris@87 1886 """
Chris@87 1887 Masked values in the input array result in rows of zeros.
Chris@87 1888 """
Chris@87 1889 _vander = np.vander(x, n)
Chris@87 1890 m = getmask(x)
Chris@87 1891 if m is not nomask:
Chris@87 1892 _vander[m] = 0
Chris@87 1893 return _vander
Chris@87 1894 vander.__doc__ = ma.doc_note(np.vander.__doc__, vander.__doc__)
Chris@87 1895
Chris@87 1896
Chris@87 1897 def polyfit(x, y, deg, rcond=None, full=False, w=None, cov=False):
Chris@87 1898 """
Chris@87 1899 Any masked values in x is propagated in y, and vice-versa.
Chris@87 1900 """
Chris@87 1901 x = asarray(x)
Chris@87 1902 y = asarray(y)
Chris@87 1903
Chris@87 1904 m = getmask(x)
Chris@87 1905 if y.ndim == 1:
Chris@87 1906 m = mask_or(m, getmask(y))
Chris@87 1907 elif y.ndim == 2:
Chris@87 1908 my = getmask(mask_rows(y))
Chris@87 1909 if my is not nomask:
Chris@87 1910 m = mask_or(m, my[:, 0])
Chris@87 1911 else:
Chris@87 1912 raise TypeError("Expected a 1D or 2D array for y!")
Chris@87 1913
Chris@87 1914 if w is not None:
Chris@87 1915 w = asarray(w)
Chris@87 1916 if w.ndim != 1:
Chris@87 1917 raise TypeError("expected a 1-d array for weights")
Chris@87 1918 if w.shape[0] != y.shape[0] :
Chris@87 1919 raise TypeError("expected w and y to have the same length")
Chris@87 1920 m = mask_or(m, getmask(w))
Chris@87 1921
Chris@87 1922 if m is not nomask:
Chris@87 1923 if w is not None:
Chris@87 1924 w = ~m*w
Chris@87 1925 else:
Chris@87 1926 w = ~m
Chris@87 1927
Chris@87 1928 return np.polyfit(x, y, deg, rcond, full, w, cov)
Chris@87 1929
Chris@87 1930 polyfit.__doc__ = ma.doc_note(np.polyfit.__doc__, polyfit.__doc__)
Chris@87 1931
Chris@87 1932 ################################################################################