[Scipy-svn] r2584 - in trunk/Lib/sandbox/maskedarray: . tests
scipy-svn at scipy.org
scipy-svn at scipy.org
Sun Jan 21 18:55:08 EST 2007
Author: pierregm
Date: 2007-01-21 17:55:03 -0600 (Sun, 21 Jan 2007)
New Revision: 2584
Modified:
trunk/Lib/sandbox/maskedarray/CHANGELOG
trunk/Lib/sandbox/maskedarray/core.py
trunk/Lib/sandbox/maskedarray/tests/test_core.py
Log:
fixed max/min_fill_value & sort
Modified: trunk/Lib/sandbox/maskedarray/CHANGELOG
===================================================================
--- trunk/Lib/sandbox/maskedarray/CHANGELOG 2007-01-21 09:11:09 UTC (rev 2583)
+++ trunk/Lib/sandbox/maskedarray/CHANGELOG 2007-01-21 23:55:03 UTC (rev 2584)
@@ -1,3 +1,6 @@
+#2007-01-21 : core : fixed max/min_fill_values
+# : : fixed sort (as method and function)
+#2007-01-18 : core : fixed default filling values for unsigned int_.
#2007-01-16 : extras : new function : `mediff1d`
#2007-01-15 : mrecords: new method: `addfield`
# : core : Force the mask of a masked array `x` to be copied w/...
Modified: trunk/Lib/sandbox/maskedarray/core.py
===================================================================
--- trunk/Lib/sandbox/maskedarray/core.py 2007-01-21 09:11:09 UTC (rev 2583)
+++ trunk/Lib/sandbox/maskedarray/core.py 2007-01-21 23:55:03 UTC (rev 2584)
@@ -66,6 +66,7 @@
import numpy.core.fromnumeric as fromnumeric
from numpy.core.numeric import ndarray
from numpy.core.fromnumeric import amax, amin
+import numpy.core.numerictypes as ntypes
from numpy.core.numerictypes import bool_, typecodes
from numpy.core.multiarray import dtype
import numpy.core.numeric as numeric
@@ -140,16 +141,36 @@
'i' : 999999,
'O' : '?',
'S' : 'N/A',
+ 'u' : 999999,
'V' : '???',
}
-max_filler = {'b': False,
- 'f' : -numeric.inf,
- 'i' : -sys.maxint,
- }
-min_filler = {'b' : True,
- 'f' : numeric.inf,
- 'i' : sys.maxint,
- }
+#{0: <type 'numpy.bool_'>,
+# 1: <type 'numpy.int8'>,
+# 2: <type 'numpy.uint8'>,
+# 3: <type 'numpy.int16'>,
+# 4: <type 'numpy.uint16'>,
+# 5: <type 'numpy.int32'>,
+# 6: <type 'numpy.uint32'>,
+# 7: <type 'numpy.int64'>,
+# 8: <type 'numpy.uint64'>,
+# 9: <type 'numpy.int64'>,
+# 10: <type 'numpy.uint64'>,
+# 11: <type 'numpy.float32'>,
+# 12: <type 'numpy.float64'>,
+# 13: <type 'numpy.float128'>,
+# 14: <type 'numpy.complex64'>,
+# 15: <type 'numpy.complex128'>,
+# 16: <type 'numpy.complex256'>,
+# 17: <type 'numpy.object_'>,
+# 18: <type 'numpy.string_'>,
+# 19: <type 'numpy.unicode_'>,
+# 20: <type 'numpy.void'>,
+max_filler = ntypes._minvals
+max_filler.update([(k,-numeric.inf) for k in
+ [numpy.float32, numpy.float64, numpy.float128]])
+min_filler = ntypes._maxvals
+min_filler.update([(k,numeric.inf) for k in
+ [numpy.float32, numpy.float64, numpy.float128]])
def default_fill_value (obj):
@@ -172,33 +193,40 @@
def minimum_fill_value (obj):
"Calculates the default fill value suitable for taking the minimum of `obj`."
if hasattr(obj, 'dtype'):
- objtype = obj.dtype.kind
- try:
- return min_filler[objtype]
- except KeyError:
+ objtype = obj.dtype
+ filler = min_filler[objtype]
+ if filler is None:
raise TypeError, 'Unsuitable type for calculating minimum.'
+ return filler
elif isinstance(obj, float):
- return min_filler['f']
- elif isinstance(obj, int) or isinstance(obj, long):
- return min_filler['i']
+ return min_filler[ntypes.typeDict['float_']]
+ elif isinstance(obj, int):
+ return min_filler[ntypes.typeDict['int_']]
+ elif isinstance(obj, long):
+ return min_filler[ntypes.typeDict['uint']]
+ elif isinstance(obj, numeric.dtype):
+ return min_filler[obj]
else:
raise TypeError, 'Unsuitable type for calculating minimum.'
def maximum_fill_value (obj):
"Calculates the default fill value suitable for taking the maximum of `obj`."
if hasattr(obj, 'dtype'):
- objtype = obj.dtype.kind
- try:
- return max_filler[objtype]
- except KeyError:
- raise TypeError, 'Unsuitable type for calculating maximum.'
+ objtype = obj.dtype
+ filler = max_filler[objtype]
+ if filler is None:
+ raise TypeError, 'Unsuitable type for calculating minimum.'
+ return filler
elif isinstance(obj, float):
- return max_filler['f']
- elif isinstance(obj, int) or isinstance(obj, long):
- #TODO: Check what happens to 'UnsignedInteger'!
- return max_filler['i']
+ return max_filler[ntypes.typeDict['float_']]
+ elif isinstance(obj, int):
+ return max_filler[ntypes.typeDict['int_']]
+ elif isinstance(obj, long):
+ return max_filler[ntypes.typeDict['uint']]
+ elif isinstance(obj, numeric.dtype):
+ return max_filler[obj]
else:
- raise TypeError, 'Unsuitable type for calculating maximum.'
+ raise TypeError, 'Unsuitable type for calculating minimum.'
def set_fill_value (a, fill_value):
"Sets the fill value of `a` if it is a masked array."
@@ -896,7 +924,6 @@
cls._defaultmask = mask
# logging.debug("__new__ returned %s as %s" % (type(_data), cls))
return numeric.asanyarray(_data).view(cls)
-
#..................................
def __array_wrap__(self, obj, context=None):
"""Special hook for ufuncs.
@@ -904,9 +931,10 @@
"""
# mclass = self.__class__
#..........
-# logging.debug("__wrap__ received %s" % type(obj))
+# logging.debug("__wrap__ received %s w/ context:%ss" % (type(obj),context))
if context is None:
# return mclass(obj, mask=self._mask, copy=False)
+# logging.debug("__wrap__ received nocontext")
return MaskedArray(obj, mask=self._mask, copy=False,
dtype=obj.dtype,
fill_value=self.fill_value, )
@@ -927,6 +955,7 @@
if m.shape != dshape:
m = reduce(mask_or, [getmaskarray(arg) for arg in args])
# return mclass(obj, copy=False, mask=m)
+# logging.debug("__wrap__ context %s" % context)
return MaskedArray(obj, copy=False, mask=m,)
# dtype=obj.dtype, fill_value=self._fill_value)
#........................
@@ -938,6 +967,9 @@
# logging.debug("__finalize__ received %s" % type(obj))
if isinstance(obj, MaskedArray):
# We came here from a MaskedArray
+# logging.debug("__finalize__ recieved data %s" % obj)
+# logging.debug("__finalize__ recieved data._data %s" % obj._data)
+# logging.debug("__finalize__ recieved data.base %s" % obj.base)
self._data = obj._data
self._mask = obj._mask
self._hardmask = obj._hardmask
@@ -1851,6 +1883,59 @@
if axis is None:
return d.argmax()
return d.argmax(axis)
+
+ def sort(self, axis=-1, kind='quicksort', order=None, endwith=True):
+ """
+ Sort a along the given axis.
+
+ Keyword arguments:
+
+ axis -- axis to be sorted (default -1)
+ kind -- sorting algorithm (default 'quicksort')
+ Possible values: 'quicksort', 'mergesort', or 'heapsort'.
+ order -- If a has fields defined, then the order keyword can be the
+ field name to sort on or a list (or tuple) of field names
+ to indicate the order that fields should be used to define
+ the sort.
+ endwith--Boolean flag indicating whether missing values (if any) should
+ be forced in the upper indices (at the end of the array) or
+ lower indices (at the beginning).
+
+ Returns: None.
+
+ This method sorts 'a' in place along the given axis using the algorithm
+ specified by the kind keyword.
+
+ The various sorts may characterized by average speed, worst case
+ performance, need for work space, and whether they are stable. A stable
+ sort keeps items with the same key in the same relative order and is most
+ useful when used with argsort where the key might differ from the items
+ being sorted. The three available algorithms have the following properties:
+
+ |------------------------------------------------------|
+ | kind | speed | worst case | work space | stable|
+ |------------------------------------------------------|
+ |'quicksort'| 1 | O(n^2) | 0 | no |
+ |'mergesort'| 2 | O(n*log(n)) | ~n/2 | yes |
+ |'heapsort' | 3 | O(n*log(n)) | 0 | no |
+ |------------------------------------------------------|
+
+ All the sort algorithms make temporary copies of the data when the sort is
+ not along the last axis. Consequently, sorts along the last axis are faster
+ and use less space than sorts along other axis.
+
+ """
+
+ if endwith:
+ filler = minimum_fill_value(self.dtype)
+ else:
+ filler = maximum_fill_value(self.dtype)
+ indx = self.filled(filler).argsort(axis=axis,kind=kind,order=order)
+ self._data = self._data[indx]
+ m = self._mask
+ if m is not nomask:
+ self._mask = m[indx]
+ return
#............................................
# Backwards Compatibility. Heck...
@property
@@ -2494,6 +2579,55 @@
return d.argmax(axis=None)
return d.argmax(axis=axis)
+def sort(a, axis=-1, kind='quicksort', order=None, endwith=True):
+ """
+ Sort a along the given axis.
+
+Keyword arguments:
+
+axis -- axis to be sorted (default -1)
+kind -- sorting algorithm (default 'quicksort')
+ Possible values: 'quicksort', 'mergesort', or 'heapsort'.
+order -- If a has fields defined, then the order keyword can be the
+ field name to sort on or a list (or tuple) of field names
+ to indicate the order that fields should be used to define
+ the sort.
+endwith--Boolean flag indicating whether missing values (if any) should
+ be forced in the upper indices (at the end of the array) or
+ lower indices (at the beginning).
+
+Returns: None.
+
+This method sorts 'a' in place along the given axis using the algorithm
+specified by the kind keyword.
+
+The various sorts may characterized by average speed, worst case
+performance, need for work space, and whether they are stable. A stable
+sort keeps items with the same key in the same relative order and is most
+useful when used with argsort where the key might differ from the items
+being sorted. The three available algorithms have the following properties:
+
+|------------------------------------------------------|
+| kind | speed | worst case | work space | stable|
+|------------------------------------------------------|
+|'quicksort'| 1 | O(n^2) | 0 | no |
+|'mergesort'| 2 | O(n*log(n)) | ~n/2 | yes |
+|'heapsort' | 3 | O(n*log(n)) | 0 | no |
+|------------------------------------------------------|
+
+All the sort algorithms make temporary copies of the data when the sort is
+not along the last axis. Consequently, sorts along the last axis are faster
+and use less space than sorts along other axis.
+
+"""
+ a = numeric.asanyarray(a)
+ if endwith:
+ filler = minimum_fill_value(a)
+ else:
+ filler = maximum_fill_value(a)
+ indx = filled(a,filler).argsort(axis=axis,kind=kind,order=order)
+ return a[indx]
+
def compressed(x):
"""Returns a compressed version of a masked array (or just the array if it
wasn't masked first)."""
@@ -2679,23 +2813,6 @@
m = make_mask(mask_or(m, getmask(indices)), copy=0, small_mask=1)
return masked_array(d, mask=m)
-def sort (x, axis=-1, fill_value=None, kind='quicksort'):
- """If x does not have a mask, returns a masked array formed from the
- result of numeric.sort(x, axis).
- Otherwise, fills x with fill_value. Sort it. Sets a mask where the result
- is equal to fill_value. Note that this may have unintended consequences
- if the data contains the fill value at a non-masked site.
- If fill_value is not given the default fill value for x's type will be
- used.
- """
- if fill_value is None:
- fill_value = default_fill_value (x)
- d = filled(x, fill_value)
- s = fromnumeric.sort(d, axis=axis, kind=kind)
- if getmask(x) is nomask:
- return masked_array(s)
- return masked_values(s, fill_value, copy=0)
-
def round_(a, decimals=0, out=None):
"""Returns reference to result. Copies a and rounds to 'decimals' places.
@@ -2895,4 +3012,4 @@
MaskedArray.__dump__ = dump
MaskedArray.__dumps__ = dumps
-
+################################################################################
Modified: trunk/Lib/sandbox/maskedarray/tests/test_core.py
===================================================================
--- trunk/Lib/sandbox/maskedarray/tests/test_core.py 2007-01-21 09:11:09 UTC (rev 2583)
+++ trunk/Lib/sandbox/maskedarray/tests/test_core.py 2007-01-21 23:55:03 UTC (rev 2584)
@@ -233,7 +233,7 @@
x4 = array(x1)
# test conversion to strings
junk, garbage = str(x2), repr(x2)
- assert_equal(N.sort(x1),sort(x2, fill_value=0))
+ assert_equal(N.sort(x1),sort(x2,endwith=False))
# tests of indexing
assert type(x2[1]) is type(x1[1])
assert x1[1] == x2[1]
@@ -1027,6 +1027,39 @@
xh[0:1] = 999
assert_equal(xh._data,[999,1,2,3,4])
+
+ def check_sort(self):
+ "Test sort"
+ x = array([1,4,2,3],mask=[0,1,0,0],dtype=N.uint8)
+ #
+ sortedx = sort(x)
+ assert_equal(sortedx._data,[1,2,3,4])
+ assert_equal(sortedx._mask,[0,0,0,1])
+ #
+ sortedx = sort(x, endwith=False)
+ assert_equal(sortedx._data, [4,1,2,3])
+ assert_equal(sortedx._mask, [1,0,0,0])
+ #
+ x.sort()
+ assert_equal(x._data,[1,2,3,4])
+ assert_equal(x._mask,[0,0,0,1])
+ #
+ x = array([1,4,2,3],mask=[0,1,0,0],dtype=N.uint8)
+ x.sort(endwith=False)
+ assert_equal(x._data, [4,1,2,3])
+ assert_equal(x._mask, [1,0,0,0])
+ #
+ x = [1,4,2,3]
+ sortedx = sort(x)
+ assert(not isinstance(sorted, MaskedArray))
+ #
+ x = array([0,1,-1,-2,2], mask=nomask, dtype=N.int8)
+ sortedx = sort(x, endwith=False)
+ assert_equal(sortedx._data, [-2,-1,0,1,2])
+ x = array([0,1,-1,-2,2], mask=[0,1,0,0,1], dtype=N.int8)
+ sortedx = sort(x, endwith=False)
+ assert_equal(sortedx._data, [1,2,-2,-1,0])
+ assert_equal(sortedx._mask, [1,1,0,0,0])
#..............................................................................
#..............................................................................
More information about the Scipy-svn
mailing list