[Numpy-svn] r5256 - in trunk/numpy/ma: . tests
numpy-svn at scipy.org
numpy-svn at scipy.org
Fri Jun 6 22:17:22 EDT 2008
Author: pierregm
Date: 2008-06-06 21:17:17 -0500 (Fri, 06 Jun 2008)
New Revision: 5256
Modified:
trunk/numpy/ma/core.py
trunk/numpy/ma/tests/test_core.py
Log:
* revamped choose to accept the out and mode keywords
* revamped argmin/argmax to accept the out keyword
* revamped all/any to accept the out keyword
Modified: trunk/numpy/ma/core.py
===================================================================
--- trunk/numpy/ma/core.py 2008-06-05 23:27:52 UTC (rev 5255)
+++ trunk/numpy/ma/core.py 2008-06-07 02:17:17 UTC (rev 5256)
@@ -1131,6 +1131,20 @@
return d
+def _fill_output_mask(output, mask):
+ """Fills the mask of output (if any) with mask.
+ Private functions used for the methods accepting out as an argument."""
+ if isinstance(output,MaskedArray):
+ outmask = getattr(output, '_mask', nomask)
+ if (outmask is nomask):
+ if mask is not nomask:
+ outmask = output._mask = make_mask_none(output.shape)
+ outmask.flat = mask
+ else:
+ outmask.flat = mask
+ return output
+
+
class MaskedArray(ndarray):
"""Arrays with possibly masked values. Masked values of True
exclude the corresponding element from any computation.
@@ -1972,84 +1986,87 @@
return (self.ctypes.data, self._mask.ctypes.data)
#............................................
def all(self, axis=None, out=None):
- """Return True if all entries along the given axis are True,
- False otherwise. Masked values are considered as True during
- computation.
+ """a.all(axis=None, out=None)
+
+ Check if all of the elements of `a` are true.
- Parameter
- ----------
- axis : int, optional
- Axis along which the operation is performed. If None,
- the operation is performed on a flatten array
- out : {MaskedArray}, optional
- Alternate optional output. If not None, out should be
- a valid MaskedArray of the same shape as the output of
- self._data.all(axis).
+ Performs a logical_and over the given axis and returns the result.
+ Masked values are considered as True during computation.
+ For convenience, the output array is masked where ALL the values along the
+ current axis are masked: if the output would have been a scalar and that
+ all the values are masked, then the output is `masked`.
- Returns A masked array, where the mask is True if all data along
- -------
- the axis are masked.
+ Parameters
+ ----------
+ axis : {None, integer}
+ Axis to perform the operation over.
+ If None, perform over flattened array.
+ out : {None, array}, optional
+ Array into which the result can be placed. Its type is preserved
+ and it must be of the right shape to hold the output.
- Notes
- -----
- An exception is raised if ``out`` is not None and not of the
- same type as self.
+ See Also
+ --------
+ all : equivalent function
+
+ Example
+ -------
+ >>> array([1,2,3]).all()
+ True
+ >>> a = array([1,2,3], mask=True)
+ >>> (a.all() is masked)
+ True
"""
+ mask = self._mask.all(axis)
if out is None:
d = self.filled(True).all(axis=axis).view(type(self))
- if d.ndim > 0:
- d.__setmask__(self._mask.all(axis))
+ if d.ndim:
+ d.__setmask__(mask)
+ elif mask:
+ return masked
return d
- elif type(out) is not type(self):
- raise TypeError("The external array should have " \
- "a type %s (got %s instead)" %\
- (type(self), type(out)))
self.filled(True).all(axis=axis, out=out)
- if out.ndim:
- out.__setmask__(self._mask.all(axis))
+ if isinstance(out, MaskedArray):
+ if out.ndim or mask:
+ out.__setmask__(mask)
return out
def any(self, axis=None, out=None):
- """Returns True if at least one entry along the given axis is
- True.
+ """a.any(axis=None, out=None)
- Returns False if all entries are False.
- Masked values are considered as True during computation.
+ Check if any of the elements of `a` are true.
- Parameter
- ----------
- axis : int, optional
- Axis along which the operation is performed.
- If None, the operation is performed on a flatten array
- out : {MaskedArray}, optional
- Alternate optional output. If not None, out should be
- a valid MaskedArray of the same shape as the output of
- self._data.all(axis).
+ Performs a logical_or over the given axis and returns the result.
+ Masked values are considered as False during computation.
- Returns A masked array, where the mask is True if all data along
- -------
- the axis are masked.
+ Parameters
+ ----------
+ axis : {None, integer}
+ Axis to perform the operation over.
+ If None, perform over flattened array and return a scalar.
+ out : {None, array}, optional
+ Array into which the result can be placed. Its type is preserved
+ and it must be of the right shape to hold the output.
- Notes
- -----
- An exception is raised if ``out`` is not None and not of the
- same type as self.
+ See Also
+ --------
+ any : equivalent function
"""
+ mask = self._mask.all(axis)
if out is None:
d = self.filled(False).any(axis=axis).view(type(self))
- if d.ndim > 0:
- d.__setmask__(self._mask.all(axis))
+ if d.ndim:
+ d.__setmask__(mask)
+ elif mask:
+ d = masked
return d
- elif type(out) is not type(self):
- raise TypeError("The external array should have a type %s "\
- "(got %s instead)" %\
- (type(self), type(out)))
self.filled(False).any(axis=axis, out=out)
- if out.ndim:
- out.__setmask__(self._mask.all(axis))
+ if isinstance(out, MaskedArray):
+ if out.ndim or mask:
+ out.__setmask__(mask)
return out
@@ -2088,30 +2105,44 @@
D = self.diagonal(offset=offset, axis1=axis1, axis2=axis2)
return D.astype(dtype).filled(0).sum(axis=None)
#............................................
- def sum(self, axis=None, dtype=None):
- """Sum the array over the given axis.
+ def sum(self, axis=None, dtype=None, out=None):
+ """Return the sum of the array elements over the given axis.
+Masked elements are set to 0 internally.
- Masked elements are set to 0 internally.
+ Parameters
+ ----------
+ axis : {None, -1, int}, optional
+ Axis along which the sum is computed. The default
+ (`axis` = None) is to compute over the flattened array.
+ dtype : {None, dtype}, optional
+ Determines the type of the returned array and of the accumulator
+ where the elements are summed. If dtype has the value None and
+ the type of a is an integer type of precision less than the default
+ platform integer, then the default platform integer precision is
+ used. Otherwise, the dtype is the same as that of a.
+ out : ndarray, optional
+ Alternative output array in which to place the result. It must
+ have the same shape and buffer length as the expected output
+ but the type will be cast if necessary.
- Parameters
- ----------
- axis : int, optional
- Axis along which to perform the operation.
- If None, applies to a flattened version of the array.
- dtype : dtype, optional
- Datatype for the intermediary computation. If not given,
- the current dtype is used instead.
"""
- if self._mask is nomask:
+ _mask = ndarray.__getattribute__(self, '_mask')
+ if _mask is nomask:
mask = nomask
else:
- mask = self._mask.all(axis)
+ mask = _mask.all(axis)
if (not mask.ndim) and mask:
+ if out is not None:
+ out = masked
return masked
- result = self.filled(0).sum(axis, dtype=dtype).view(type(self))
- if result.ndim > 0:
- result.__setmask__(mask)
+ if out is None:
+ result = self.filled(0).sum(axis, dtype=dtype).view(type(self))
+ if result.ndim:
+ result.__setmask__(mask)
+ else:
+ result = self.filled(0).sum(axis, dtype=dtype, out=out)
+ _fill_output_mask(out, mask)
return result
def cumsum(self, axis=None, dtype=None):
@@ -2361,49 +2392,71 @@
fill_value = default_fill_value(self)
d = self.filled(fill_value).view(ndarray)
return d.argsort(axis=axis, kind=kind, order=order)
- #........................
- def argmin(self, axis=None, fill_value=None):
- """Return an ndarray of indices for the minimum values of a
- along the specified axis.
- Masked values are treated as if they had the value fill_value.
- Parameters
- ----------
- axis : int, optional
- Axis along which to perform the operation.
- If None, applies to a flattened version of the array.
- fill_value : {var}, optional
- Value used to fill in the masked values. If None, the
- output of minimum_fill_value(self._data) is used.
+ def argmin(self, axis=None, fill_value=None, out=None):
+ """a.argmin(axis=None, out=None)
+ Return array of indices to the minimum values along the given axis.
+
+ Parameters
+ ----------
+ axis : {None, integer}
+ If None, the index is into the flattened array, otherwise along
+ the specified axis
+ fill_value : {var}, optional
+ Value used to fill in the masked values. If None, the output of
+ minimum_fill_value(self._data) is used instead.
+ out : {None, array}, optional
+ Array into which the result can be placed. Its type is preserved
+ and it must be of the right shape to hold the output.
+
"""
if fill_value is None:
fill_value = minimum_fill_value(self)
d = self.filled(fill_value).view(ndarray)
- return d.argmin(axis)
- #........................
- def argmax(self, axis=None, fill_value=None):
- """Returns the array of indices for the maximum values of `a`
- along the specified axis.
+ return d.argmin(axis, out=out)
- Masked values are treated as if they had the value fill_value.
- Parameters
- ----------
- axis : int, optional
- Axis along which to perform the operation.
- If None, applies to a flattened version of the array.
- fill_value : {var}, optional
- Value used to fill in the masked values. If None, the
- output of maximum_fill_value(self._data) is used.
+ def argmax(self, axis=None, fill_value=None, out=None):
+ """a.argmax(axis=None, out=None)
+ Returns array of indices of the maximum values along the given axis.
+ Masked values are treated as if they had the value fill_value.
+
+ Parameters
+ ----------
+ axis : {None, integer}
+ If None, the index is into the flattened array, otherwise along
+ the specified axis
+ fill_value : {var}, optional
+ Value used to fill in the masked values. If None, the output of
+ maximum_fill_value(self._data) is used instead.
+ out : {None, array}, optional
+ Array into which the result can be placed. Its type is preserved
+ and it must be of the right shape to hold the output.
+
+ Returns
+ -------
+ index_array : {integer_array}
+
+ Examples
+ --------
+ >>> a = arange(6).reshape(2,3)
+ >>> a.argmax()
+ 5
+ >>> a.argmax(0)
+ array([1, 1, 1])
+ >>> a.argmax(1)
+ array([2, 2])
+
"""
if fill_value is None:
fill_value = maximum_fill_value(self._data)
d = self.filled(fill_value).view(ndarray)
- return d.argmax(axis)
+ return d.argmax(axis, out=out)
+
def sort(self, axis=-1, kind='quicksort', order=None,
endwith=True, fill_value=None):
"""Sort along the given axis.
@@ -3230,30 +3283,72 @@
d._mask = nomask
return d
-def choose (indices, t, out=None, mode='raise'):
- "Return array shaped like indices with elements chosen from t"
- #!!!: implement options `out` and `mode`, if possible + test.
+def choose (indices, choices, out=None, mode='raise'):
+ """
+ choose(a, choices, out=None, mode='raise')
+
+ Use an index array to construct a new array from a set of choices.
+
+ Given an array of integers and a set of n choice arrays, this method
+ will create a new array that merges each of the choice arrays. Where a
+ value in `a` is i, the new array will have the value that choices[i]
+ contains in the same place.
+
+ Parameters
+ ----------
+ a : int array
+ This array must contain integers in [0, n-1], where n is the number
+ of choices.
+ choices : sequence of arrays
+ Choice arrays. The index array and all of the choices should be
+ broadcastable to the same shape.
+ out : array, optional
+ If provided, the result will be inserted into this array. It should
+ be of the appropriate shape and dtype
+ mode : {'raise', 'wrap', 'clip'}, optional
+ Specifies how out-of-bounds indices will behave.
+ 'raise' : raise an error
+ 'wrap' : wrap around
+ 'clip' : clip to the range
+
+ Returns
+ -------
+ merged_array : array
+
+ See Also
+ --------
+ choose : equivalent function
+
+ """
def fmask (x):
"Returns the filled array, or True if masked."
if x is masked:
- return 1
+ return True
return filled(x)
def nmask (x):
"Returns the mask, True if ``masked``, False if ``nomask``."
if x is masked:
- return 1
- m = getmask(x)
- if m is nomask:
- return 0
- return m
+ return True
+ return getmask(x)
+ # Get the indices......
c = filled(indices, 0)
- masks = [nmask(x) for x in t]
- a = [fmask(x) for x in t]
- d = np.choose(c, a)
- m = np.choose(c, masks)
- m = make_mask(mask_or(m, getmask(indices)), copy=0, shrink=True)
- return masked_array(d, mask=m)
+ # Get the masks........
+ masks = [nmask(x) for x in choices]
+ data = [fmask(x) for x in choices]
+ # Construct the mask
+ outputmask = np.choose(c, masks, mode=mode)
+ outputmask = make_mask(mask_or(outputmask, getmask(indices)),
+ copy=0, shrink=True)
+ # Get the choices......
+ d = np.choose(c, data, mode=mode, out=out).view(MaskedArray)
+ if out is not None:
+ if isinstance(out, MaskedArray):
+ out.__setmask__(outputmask)
+ return out
+ d.__setmask__(outputmask)
+ return d
+
def round_(a, decimals=0, out=None):
"""Return a copy of a, rounded to 'decimals' places.
Modified: trunk/numpy/ma/tests/test_core.py
===================================================================
--- trunk/numpy/ma/tests/test_core.py 2008-06-05 23:27:52 UTC (rev 5255)
+++ trunk/numpy/ma/tests/test_core.py 2008-06-07 02:17:17 UTC (rev 5256)
@@ -1,4 +1,4 @@
-# pylint: disable-msg=W0611, W0612, W0511,R0201
+# pylint: disable-msg=W0611, W0612, W0614, W0511,R0201
"""Tests suite for MaskedArray & subclassing.
:author: Pierre Gerard-Marchant
@@ -1031,7 +1031,7 @@
#...............................................................................
-class TestArrayMethods(NumpyTestCase):
+class TestArrayMathMethods(NumpyTestCase):
"Test class for miscellaneous MaskedArrays methods."
def setUp(self):
"Base data definition."
@@ -1261,6 +1261,26 @@
assert_equal(mXsmall.any(0), numpy.matrix([True, True, False]))
assert_equal(mXsmall.any(1), numpy.matrix([True, True, False]).T)
+
+ def test_allany_oddities(self):
+ "Some fun with all and any"
+ store = empty(1, dtype=bool)
+ full = array([1,2,3], mask=True)
+ #
+ assert(full.all() is masked)
+ full.all(out=store)
+ assert(store)
+ assert(store._mask, True)
+ assert(store is not masked)
+ #
+ store = empty(1, dtype=bool)
+ assert(full.any() is masked)
+ full.any(out=store)
+ assert(not store)
+ assert(store._mask, True)
+ assert(store is not masked)
+
+
def test_keepmask(self):
"Tests the keep mask flag"
x = masked_array([1,2,3], mask=[1,0,0])
@@ -1587,7 +1607,7 @@
assert_equal(b.shape, a.shape)
assert_equal(b.fill_value, a.fill_value)
-class TestArrayMethodsComplex(NumpyTestCase):
+class TestArrayMathMethodsComplex(NumpyTestCase):
"Test class for miscellaneous MaskedArrays methods."
def setUp(self):
"Base data definition."
@@ -1685,7 +1705,53 @@
assert_almost_equal(x._data,y._data)
+ def test_choose(self):
+ "Test choose"
+ choices = [[0, 1, 2, 3], [10, 11, 12, 13],
+ [20, 21, 22, 23], [30, 31, 32, 33]]
+ chosen = choose([2, 3, 1, 0], choices)
+ assert_equal(chosen, array([20, 31, 12, 3]))
+ chosen = choose([2, 4, 1, 0], choices, mode='clip')
+ assert_equal(chosen, array([20, 31, 12, 3]))
+ chosen = choose([2, 4, 1, 0], choices, mode='wrap')
+ assert_equal(chosen, array([20, 1, 12, 3]))
+ # Check with some masked indices
+ indices_ = array([2, 4, 1, 0], mask=[1,0,0,1])
+ chosen = choose(indices_, choices, mode='wrap')
+ assert_equal(chosen, array([99, 1, 12, 99]))
+ assert_equal(chosen.mask, [1,0,0,1])
+ # Check with some masked choices
+ choices = array(choices, mask=[[0, 0, 0, 1], [1, 1, 0, 1],
+ [1, 0, 0, 0], [0, 0, 0, 0]])
+ indices_ = [2, 3, 1, 0]
+ chosen = choose(indices_, choices, mode='wrap')
+ assert_equal(chosen, array([20, 31, 12, 3]))
+ assert_equal(chosen.mask, [1,0,0,1])
+
+ def test_choose_with_out(self):
+ "Test choose with an explicit out keyword"
+ choices = [[0, 1, 2, 3], [10, 11, 12, 13],
+ [20, 21, 22, 23], [30, 31, 32, 33]]
+ store = empty(4, dtype=int)
+ chosen = choose([2, 3, 1, 0], choices, out=store)
+ assert_equal(store, array([20, 31, 12, 3]))
+ assert(store is chosen)
+ # Check with some masked indices + out
+ store = empty(4, dtype=int)
+ indices_ = array([2, 3, 1, 0], mask=[1,0,0,1])
+ chosen = choose(indices_, choices, mode='wrap', out=store)
+ assert_equal(store, array([99, 31, 12, 99]))
+ assert_equal(store.mask, [1,0,0,1])
+ # Check with some masked choices + out ina ndarray !
+ choices = array(choices, mask=[[0, 0, 0, 1], [1, 1, 0, 1],
+ [1, 0, 0, 0], [0, 0, 0, 0]])
+ indices_ = [2, 3, 1, 0]
+ store = empty(4, dtype=int).view(ndarray)
+ chosen = choose(indices_, choices, mode='wrap', out=store)
+ assert_equal(store, array([999999, 31, 12, 999999]))
+
+
###############################################################################
#------------------------------------------------------------------------------
if __name__ == "__main__":
More information about the Numpy-svn
mailing list