summaryrefslogtreecommitdiff
path: root/numpy
diff options
context:
space:
mode:
authorRobert Cimrman <cimrman3@ntc.zcu.cz>2009-07-08 15:46:09 +0000
committerRobert Cimrman <cimrman3@ntc.zcu.cz>2009-07-08 15:46:09 +0000
commitc1c0533f20e349b5e638025ef173aa487b2422c7 (patch)
treee2fef41c590d17bbacae0ec36d447d13cf21afb6 /numpy
parent434bc70004d63ed44dd5d793d5eb65b840f39362 (diff)
downloadnumpy-c1c0533f20e349b5e638025ef173aa487b2422c7.tar.gz
Enhancements to arraysetops (ticket #1133, by Neil Crighton)
Diffstat (limited to 'numpy')
-rw-r--r--numpy/lib/arraysetops.py360
-rw-r--r--numpy/lib/function_base.py29
-rw-r--r--numpy/lib/info.py7
-rw-r--r--numpy/lib/tests/test_arraysetops.py87
-rw-r--r--numpy/ma/extras.py173
-rw-r--r--numpy/ma/tests/test_extras.py56
6 files changed, 362 insertions, 350 deletions
diff --git a/numpy/lib/arraysetops.py b/numpy/lib/arraysetops.py
index b1a730efa..fe1326aa0 100644
--- a/numpy/lib/arraysetops.py
+++ b/numpy/lib/arraysetops.py
@@ -3,40 +3,36 @@ Set operations for 1D numeric arrays based on sorting.
:Contains:
ediff1d,
- unique1d,
+ unique,
intersect1d,
- intersect1d_nu,
setxor1d,
- setmember1d,
- setmember1d_nu,
+ in1d,
union1d,
setdiff1d
+:Deprecated:
+ unique1d,
+ intersect1d_nu,
+ setmember1d
+
:Notes:
-All functions work best with integer numerical arrays on input (e.g. indices).
-For floating point arrays, innacurate results may appear due to usual round-off
+For floating point arrays, inaccurate results may appear due to usual round-off
and floating point comparison issues.
-Except unique1d, union1d and intersect1d_nu, all functions expect inputs with
-unique elements. Speed could be gained in some operations by an implementaion of
-sort(), that can provide directly the permutation vectors, avoiding thus calls
-to argsort().
-
-Run _test_unique1d_speed() to compare performance of numpy.unique1d() and
-numpy.unique() - it should be the same.
+Speed could be gained in some operations by an implementation of
+sort(), that can provide directly the permutation vectors, avoiding
+thus calls to argsort().
-To do: Optionally return indices analogously to unique1d for all functions.
-
-created: 01.11.2005
-last revision: 07.01.2007
+To do: Optionally return indices analogously to unique for all functions.
:Author: Robert Cimrman
"""
__all__ = ['ediff1d', 'unique1d', 'intersect1d', 'intersect1d_nu', 'setxor1d',
- 'setmember1d', 'setmember1d_nu', 'union1d', 'setdiff1d']
+ 'setmember1d', 'union1d', 'setdiff1d', 'unique', 'in1d']
import numpy as np
+from numpy.lib.utils import deprecate_with_doc
def ediff1d(ary, to_end=None, to_begin=None):
"""
@@ -46,45 +42,23 @@ def ediff1d(ary, to_end=None, to_begin=None):
----------
ary : array
This array will be flattened before the difference is taken.
- to_end : array_like, optional
- If provided, this number will be appended to the end of the returned
+ to_end : number, optional
+ If provided, this number will be tacked onto the end of the returned
differences.
- to_begin : array_like, optional
- If provided, this array will be appended to the beginning of the
+ to_begin : number, optional
+ If provided, this number will be tacked onto the beginning of the
returned differences.
Returns
-------
ed : array
- The differences. Loosely, this will be ``ary[1:] - ary[:-1]``.
-
- See Also
- --------
- diff, gradient
+ The differences. Loosely, this will be (ary[1:] - ary[:-1]).
Notes
-----
When applied to masked arrays, this function drops the mask information
if the `to_begin` and/or `to_end` parameters are used
- Examples
- --------
- >>> x = np.array([1, 2, 4, 7, 0])
- >>> np.ediff1d(x)
- array([ 1, 2, 3, -7])
-
- >>> np.ediff1d(x, to_begin=-99, to_end=np.array([88, 99]))
- array([-99, 1, 2, 3, -7, 88, 99])
-
- The returned array is always 1D.
-
- >>> y = np.array([[1, 2, 4], [1, 6, 24]])
- >>> y
- array([[ 1, 2, 4],
- [ 1, 6, 24]])
- >>> np.ediff1d(y)
- array([ 1, 2, -3, 5, 18])
-
"""
ary = np.asanyarray(ary).flat
ed = ary[1:] - ary[:-1]
@@ -95,26 +69,26 @@ def ediff1d(ary, to_end=None, to_begin=None):
arrays.append(to_end)
if len(arrays) != 1:
- # We'll save ourselves a copy of a potentially large array in the common
- # case where neither to_begin or to_end was given.
+ # We'll save ourselves a copy of a potentially large array in
+ # the common case where neither to_begin or to_end was given.
ed = np.hstack(arrays)
return ed
-def unique1d(ar1, return_index=False, return_inverse=False):
+def unique(ar, return_index=False, return_inverse=False):
"""
Find the unique elements of an array.
Parameters
----------
- ar1 : array_like
+ ar : array_like
This array will be flattened if it is not already 1-D.
return_index : bool, optional
If True, also return the indices against `ar1` that result in the
unique array.
return_inverse : bool, optional
If True, also return the indices against the unique array that
- result in `ar1`.
+ result in `ar`.
Returns
-------
@@ -134,17 +108,17 @@ def unique1d(ar1, return_index=False, return_inverse=False):
Examples
--------
- >>> np.unique1d([1, 1, 2, 2, 3, 3])
+ >>> np.unique([1, 1, 2, 2, 3, 3])
array([1, 2, 3])
>>> a = np.array([[1, 1], [2, 3]])
- >>> np.unique1d(a)
+ >>> np.unique(a)
array([1, 2, 3])
Reconstruct the input from unique values:
- >>> np.unique1d([1,2,6,4,2,3,2], return_index=True)
+ >>> np.unique([1,2,6,4,2,3,2], return_index=True)
>>> x = [1,2,6,4,2,3,2]
- >>> u, i = np.unique1d(x, return_inverse=True)
+ >>> u, i = np.unique(x, return_inverse=True)
>>> u
array([1, 2, 3, 4, 6])
>>> i
@@ -153,14 +127,15 @@ def unique1d(ar1, return_index=False, return_inverse=False):
[1, 2, 6, 4, 2, 3, 2]
"""
- if return_index:
- import warnings
- warnings.warn("The order of the output arguments for "
- "`return_index` has changed. Before, "
- "the output was (indices, unique_arr), but "
- "has now been reversed to be more consistent.")
+ try:
+ ar = ar.flatten()
+ except AttributeError:
+ if not return_inverse and not return_index:
+ items = sorted(set(ar))
+ return np.asarray(items)
+ else:
+ ar = np.asanyarray(ar).flatten()
- ar = np.asanyarray(ar1).flatten()
if ar.size == 0:
if return_inverse and return_index:
return ar, np.empty(0, np.bool), np.empty(0, np.bool)
@@ -188,98 +163,54 @@ def unique1d(ar1, return_index=False, return_inverse=False):
flag = np.concatenate(([True], ar[1:] != ar[:-1]))
return ar[flag]
-def intersect1d(ar1, ar2):
- """
- Find elements that are common to two arrays.
-
- For speed, it is assumed the two input arrays do not have any
- repeated elements. To find the intersection of two arrays that
- have repeated elements, use `intersect1d_nu`.
-
- Parameters
- ----------
- ar1,ar2 : array_like
- Input arrays. These must be 1D and must not have repeated elements.
-
- Returns
- -------
- out : ndarray, shape(N,)
- Sorted array of common elements.
-
- See Also
- --------
- intersect1d_nu : Find the intersection for input arrays with
- repeated elements.
- numpy.lib.arraysetops : Module with a number of other functions for
- performing set operations on arrays.
- Examples
- --------
- >>> np.intersect1d([1, 2, 3], [2, 3, 4])
- array([2, 3])
- >>> np.intersect1d(['a','b','c'], ['b','c','d'])
- array(['b', 'c'],
- dtype='|S1')
-
- This function fails if the input arrays have repeated elements.
-
- >>> np.intersect1d([1, 1, 2, 3, 3, 4], [1, 4])
- array([1, 1, 3, 4])
-
- """
- aux = np.concatenate((ar1,ar2))
- aux.sort()
- return aux[aux[1:] == aux[:-1]]
-
-def intersect1d_nu(ar1, ar2):
+def intersect1d(ar1, ar2, assume_unique=False):
"""
- Find elements common to two arrays.
-
- Returns an array of unique elements that represents the intersection
- of the two input arrays. Unlike `intersect1d`, the input arrays can
- have repeated elements.
+ Intersection returning unique elements common to both arrays.
Parameters
----------
- ar1,ar2 : array_like
+ ar1, ar2 : array_like
Input arrays.
+ assume_unique : bool
+ If True, the input arrays are both assumed to be unique, which
+ can speed up the calculation. Default is False.
Returns
-------
out : ndarray, shape(N,)
- Sorted 1D array of common, unique elements.
+ Sorted 1D array of common and unique elements.
See Also
--------
- intersect1d : Faster version of `intersect1d_nu` for 1D input arrays
- without repeated elements.
numpy.lib.arraysetops : Module with a number of other functions for
performing set operations on arrays.
Examples
--------
- >>> np.intersect1d_nu([1, 3 ,3], [3, 3, 1, 1])
+ >>> np.intersect1d([1,3,3], [3,1,1])
array([1, 3])
"""
- # Might be faster than unique1d( intersect1d( ar1, ar2 ) )?
- aux = np.concatenate((unique1d(ar1), unique1d(ar2)))
+ if not assume_unique:
+ # Might be faster than unique( intersect1d( ar1, ar2 ) )?
+ ar1 = unique(ar1)
+ ar2 = unique(ar2)
+ aux = np.concatenate( (ar1, ar2) )
aux.sort()
return aux[aux[1:] == aux[:-1]]
-def setxor1d(ar1, ar2):
+def setxor1d(ar1, ar2, assume_unique=False):
"""
- Set exclusive-or of 1D arrays with unique elements.
-
- Use unique1d() to generate arrays with only unique elements to use as
- inputs to this function.
+ Set exclusive-or of two 1D arrays.
Parameters
----------
- ar1 : array_like
- Input array.
- ar2 : array_like
- Input array.
+ ar1, ar2 : array_like
+ Input arrays.
+ assume_unique : bool
+ If True, the input arrays are both assumed to be unique, which
+ can speed up the calculation. Default is False.
Returns
-------
@@ -292,7 +223,11 @@ def setxor1d(ar1, ar2):
performing set operations on arrays.
"""
- aux = np.concatenate((ar1, ar2))
+ if not assume_unique:
+ ar1 = unique(ar1)
+ ar2 = unique(ar2)
+
+ aux = np.concatenate( (ar1, ar2) )
if aux.size == 0:
return aux
@@ -303,21 +238,20 @@ def setxor1d(ar1, ar2):
flag2 = flag[1:] == flag[:-1]
return aux[flag2]
-def setmember1d(ar1, ar2):
+def in1d(ar1, ar2, assume_unique=False):
"""
- Test whether elements of one array are also present in a second array.
+ Test whether each element of an array is also present in a second array.
- Returns a boolean array the same length as `ar1` that is True where an
- element of `ar1` is also in `ar2` and False otherwise. The input arrays
- must not contain any repeated elements. If they do, unique arrays can
- be created using `unique1d()` to use as inputs to this function.
+ Returns a boolean array the same length as `ar1` that is True
+ where an element of `ar1` is in `ar2` and False otherwise.
Parameters
----------
- ar1 : array_like
- Input array. It must not have any repeated elements
- ar2 : array_like
- Input array. Again, it must not have any repeated elements.
+ ar1, ar2 : array_like
+ Input arrays.
+ assume_unique : bool
+ If True, the input arrays are both assumed to be unique, which
+ can speed up the calculation. Default is False.
Returns
-------
@@ -326,14 +260,16 @@ def setmember1d(ar1, ar2):
See Also
--------
- setmember1d_nu : Works for arrays with non-unique elements.
numpy.lib.arraysetops : Module with a number of other functions for
performing set operations on arrays.
- unique1d : Find unique elements in an array.
+
+ Notes
+ -----
+ .. versionadded:: 1.4.0
Examples
--------
- >>> test = [0, 1, 2, 3, 4, 5]
+ >>> test = np.arange(5)
>>> states = [0, 2]
>>> mask = np.setmember1d(test, states)
>>> mask
@@ -341,66 +277,29 @@ def setmember1d(ar1, ar2):
>>> test[mask]
array([0, 2])
- This function fails if there are repeated elements in the input arrays:
-
- >>> test = [0, 1, 1, 2, 3, 3]
- >>> states = [0, 2]
- >>> np.setmember1d(test,states)
- array([ True, True, False, True, True, False], dtype=bool) # Wrong!
-
"""
- # We need this to be a stable sort, so always use 'mergesort' here. The
- # values from the first array should always come before the values from the
- # second array.
- ar = np.concatenate( (ar1, ar2 ) )
+ if not assume_unique:
+ ar1, rev_idx = np.unique(ar1, return_inverse=True)
+ ar2 = np.unique(ar2)
+
+ ar = np.concatenate( (ar1, ar2) )
+ # We need this to be a stable sort, so always use 'mergesort'
+ # here. The values from the first array should always come before
+ # the values from the second array.
order = ar.argsort(kind='mergesort')
sar = ar[order]
equal_adj = (sar[1:] == sar[:-1])
flag = np.concatenate( (equal_adj, [False] ) )
-
indx = order.argsort(kind='mergesort')[:len( ar1 )]
- return flag[indx]
-
-def setmember1d_nu(ar1, ar2):
- """
- Return a boolean array set True where first element is in second array.
-
- Boolean array is the shape of `ar1` containing True where the elements
- of `ar1` are in `ar2` and False otherwise.
-
- Unlike setmember1d(), this version works also for arrays with duplicate
- values. It uses setmember1d() internally. For arrays with unique
- entries it is slower than calling setmember1d() directly.
-
- Parameters
- ----------
- ar1 : array_like
- Input array.
- ar2 : array_like
- Input array.
-
- Returns
- -------
- mask : ndarray, bool
- The values `ar1[mask]` are in `ar2`.
- See Also
- --------
- setmember1d : Faster for arrays with unique elements.
- numpy.lib.arraysetops : Module with a number of other functions for
- performing set operations on arrays.
-
- """
- unique_ar1, rev_idx = np.unique1d(ar1, return_inverse=True)
- mask = np.setmember1d(unique_ar1, np.unique1d(ar2))
- return mask[rev_idx]
+ if assume_unique:
+ return flag[indx]
+ else:
+ return flag[indx][rev_idx]
def union1d(ar1, ar2):
"""
- Union of 1D arrays with unique elements.
-
- Use unique1d() to generate arrays with only unique elements to use as
- inputs to this function.
+ Union of two 1D arrays.
Parameters
----------
@@ -420,14 +319,11 @@ def union1d(ar1, ar2):
performing set operations on arrays.
"""
- return unique1d( np.concatenate( (ar1, ar2) ) )
+ return unique( np.concatenate( (ar1, ar2) ) )
-def setdiff1d(ar1, ar2):
+def setdiff1d(ar1, ar2, assume_unique=False):
"""
- Set difference of 1D arrays with unique elements.
-
- Use unique1d() to generate arrays with only unique elements to use as
- inputs to this function.
+ Set difference of two 1D arrays.
Parameters
----------
@@ -435,6 +331,9 @@ def setdiff1d(ar1, ar2):
Input array.
ar2 : array_like
Input comparison array.
+ assume_unique : bool
+ If True, the input arrays are both assumed to be unique, which
+ can speed up the calculation. Default is False.
Returns
-------
@@ -447,8 +346,77 @@ def setdiff1d(ar1, ar2):
performing set operations on arrays.
"""
- aux = setmember1d(ar1,ar2)
+ aux = in1d(ar1, ar2, assume_unique=assume_unique)
if aux.size == 0:
return aux
else:
return np.asarray(ar1)[aux == 0]
+
+@deprecate_with_doc('')
+def unique1d(ar1, return_index=False, return_inverse=False):
+ """
+ This function is deprecated. Use unique() instead.
+ """
+ if return_index:
+ import warnings
+ warnings.warn("The order of the output arguments for "
+ "`return_index` has changed. Before, "
+ "the output was (indices, unique_arr), but "
+ "has now been reversed to be more consistent.")
+
+ ar = np.asanyarray(ar1).flatten()
+ if ar.size == 0:
+ if return_inverse and return_index:
+ return ar, np.empty(0, np.bool), np.empty(0, np.bool)
+ elif return_inverse or return_index:
+ return ar, np.empty(0, np.bool)
+ else:
+ return ar
+
+ if return_inverse or return_index:
+ perm = ar.argsort()
+ aux = ar[perm]
+ flag = np.concatenate(([True], aux[1:] != aux[:-1]))
+ if return_inverse:
+ iflag = np.cumsum(flag) - 1
+ iperm = perm.argsort()
+ if return_index:
+ return aux[flag], perm[flag], iflag[iperm]
+ else:
+ return aux[flag], iflag[iperm]
+ else:
+ return aux[flag], perm[flag]
+
+ else:
+ ar.sort()
+ flag = np.concatenate(([True], ar[1:] != ar[:-1]))
+ return ar[flag]
+
+@deprecate_with_doc('')
+def intersect1d_nu(ar1, ar2):
+ """
+ This function is deprecated. Use intersect1d()
+ instead.
+ """
+ # Might be faster than unique1d( intersect1d( ar1, ar2 ) )?
+ aux = np.concatenate((unique1d(ar1), unique1d(ar2)))
+ aux.sort()
+ return aux[aux[1:] == aux[:-1]]
+
+@deprecate_with_doc('')
+def setmember1d(ar1, ar2):
+ """
+ This function is deprecated. Use in1d(assume_unique=True)
+ instead.
+ """
+ # We need this to be a stable sort, so always use 'mergesort' here. The
+ # values from the first array should always come before the values from the
+ # second array.
+ ar = np.concatenate( (ar1, ar2 ) )
+ order = ar.argsort(kind='mergesort')
+ sar = ar[order]
+ equal_adj = (sar[1:] == sar[:-1])
+ flag = np.concatenate( (equal_adj, [False] ) )
+
+ indx = order.argsort(kind='mergesort')[:len( ar1 )]
+ return flag[indx]
diff --git a/numpy/lib/function_base.py b/numpy/lib/function_base.py
index e596d8810..d56e69611 100644
--- a/numpy/lib/function_base.py
+++ b/numpy/lib/function_base.py
@@ -3,7 +3,7 @@ __all__ = ['logspace', 'linspace',
'select', 'piecewise', 'trim_zeros',
'copy', 'iterable',
'diff', 'gradient', 'angle', 'unwrap', 'sort_complex', 'disp',
- 'unique', 'extract', 'place', 'nansum', 'nanmax', 'nanargmax',
+ 'extract', 'place', 'nansum', 'nanmax', 'nanargmax',
'nanargmin', 'nanmin', 'vectorize', 'asarray_chkfinite', 'average',
'histogram', 'histogramdd', 'bincount', 'digitize', 'cov',
'corrcoef', 'msort', 'median', 'sinc', 'hamming', 'hanning',
@@ -28,6 +28,7 @@ from numpy.lib.twodim_base import diag
from _compiled_base import _insert, add_docstring
from _compiled_base import digitize, bincount, interp as compiled_interp
from arraysetops import setdiff1d
+from utils import deprecate_with_doc
import numpy as np
#end Fernando's utilities
@@ -1345,31 +1346,11 @@ import sys
if sys.hexversion < 0x2040000:
from sets import Set as set
+@deprecate_with_doc('')
def unique(x):
"""
- Return the sorted, unique elements of an array or sequence.
-
- Parameters
- ----------
- x : ndarray or sequence
- Input array.
-
- Returns
- -------
- y : ndarray
- The sorted, unique elements are returned in a 1-D array.
-
- Examples
- --------
- >>> np.unique([1, 1, 2, 2, 3, 3])
- array([1, 2, 3])
- >>> a = np.array([[1, 1], [2, 3]])
- >>> np.unique(a)
- array([1, 2, 3])
-
- >>> np.unique([True, True, False])
- array([False, True], dtype=bool)
-
+ This function is deprecated. Use numpy.lib.arraysetops.unique()
+ instead.
"""
try:
tmp = x.flatten()
diff --git a/numpy/lib/info.py b/numpy/lib/info.py
index f93234d57..4a781a2ca 100644
--- a/numpy/lib/info.py
+++ b/numpy/lib/info.py
@@ -135,12 +135,11 @@ Set operations for 1D numeric arrays based on sort() function.
================ ===================
ediff1d Array difference (auxiliary function).
-unique1d Unique elements of 1D array.
+unique Unique elements of an array.
intersect1d Intersection of 1D arrays with unique elements.
-intersect1d_nu Intersection of 1D arrays with any elements.
setxor1d Set exclusive-or of 1D arrays with unique elements.
-setmember1d Return an array of shape of ar1 containing 1 where
- the elements of ar1 are in ar2 and 0 otherwise.
+in1d Test whether elements in a 1D array are also present in
+ another array.
union1d Union of 1D arrays with unique elements.
setdiff1d Set difference of 1D arrays with unique elements.
================ ===================
diff --git a/numpy/lib/tests/test_arraysetops.py b/numpy/lib/tests/test_arraysetops.py
index 40bc11f6e..a83ab1394 100644
--- a/numpy/lib/tests/test_arraysetops.py
+++ b/numpy/lib/tests/test_arraysetops.py
@@ -9,39 +9,61 @@ from numpy.lib.arraysetops import *
import warnings
class TestAso(TestCase):
- def test_unique1d( self ):
+ def test_unique( self ):
a = np.array( [5, 7, 1, 2, 1, 5, 7] )
ec = np.array( [1, 2, 5, 7] )
- c = unique1d( a )
+ c = unique( a )
assert_array_equal( c, ec )
warnings.simplefilter('ignore', Warning)
- unique, indices = unique1d( a, return_index=True )
+ vals, indices = unique( a, return_index=True )
warnings.resetwarnings()
ed = np.array( [2, 3, 0, 1] )
- assert_array_equal(unique, ec)
+ assert_array_equal(vals, ec)
assert_array_equal(indices, ed)
- assert_array_equal([], unique1d([]))
+ warnings.simplefilter('ignore', Warning)
+ vals, ind0, ind1 = unique( a, return_index=True,
+ return_inverse=True )
+ warnings.resetwarnings()
+
+ ee = np.array( [2, 3, 0, 1, 0, 2, 3] )
+ assert_array_equal(vals, ec)
+ assert_array_equal(ind0, ed)
+ assert_array_equal(ind1, ee)
+
+ assert_array_equal([], unique([]))
def test_intersect1d( self ):
+ # unique inputs
a = np.array( [5, 7, 1, 2] )
b = np.array( [2, 4, 3, 1, 5] )
ec = np.array( [1, 2, 5] )
- c = intersect1d( a, b )
+ c = intersect1d( a, b, assume_unique=True )
assert_array_equal( c, ec )
+ # non-unique inputs
+ a = np.array( [5, 5, 7, 1, 2] )
+ b = np.array( [2, 1, 4, 3, 3, 1, 5] )
+
+ ed = np.array( [1, 2, 5] )
+ c = intersect1d( a, b )
+ assert_array_equal( c, ed )
+
assert_array_equal([], intersect1d([],[]))
def test_intersect1d_nu( self ):
+ # This should be removed when intersect1d_nu is removed.
a = np.array( [5, 5, 7, 1, 2] )
b = np.array( [2, 1, 4, 3, 3, 1, 5] )
ec = np.array( [1, 2, 5] )
+ warnings.simplefilter('ignore', Warning)
c = intersect1d_nu( a, b )
+ warnings.resetwarnings()
assert_array_equal( c, ec )
assert_array_equal([], intersect1d_nu([],[]))
@@ -83,11 +105,14 @@ class TestAso(TestCase):
assert_array_equal([1],ediff1d(two_elem))
def test_setmember1d( self ):
+ # This should be removed when setmember1d is removed.
a = np.array( [5, 7, 1, 2] )
b = np.array( [2, 4, 3, 1, 5] )
ec = np.array( [True, False, True, True] )
+ warnings.simplefilter('ignore', Warning)
c = setmember1d( a, b )
+ warnings.resetwarnings()
assert_array_equal( c, ec )
a[0] = 8
@@ -102,51 +127,77 @@ class TestAso(TestCase):
assert_array_equal([], setmember1d([],[]))
- def test_setmember1d_nu(self):
+ def test_in1d(self):
+ a = np.array( [5, 7, 1, 2] )
+ b = np.array( [2, 4, 3, 1, 5] )
+
+ ec = np.array( [True, False, True, True] )
+ c = in1d( a, b, assume_unique=True )
+ assert_array_equal( c, ec )
+
+ a[0] = 8
+ ec = np.array( [False, False, True, True] )
+ c = in1d( a, b, assume_unique=True )
+ assert_array_equal( c, ec )
+
+ a[0], a[3] = 4, 8
+ ec = np.array( [True, False, True, False] )
+ c = in1d( a, b, assume_unique=True )
+ assert_array_equal( c, ec )
+
a = np.array([5,4,5,3,4,4,3,4,3,5,2,1,5,5])
b = [2,3,4]
ec = [False, True, False, True, True, True, True, True, True, False,
True, False, False, False]
- c = setmember1d_nu(a, b)
+ c = in1d(a, b)
assert_array_equal(c, ec)
b = b + [5, 5, 4]
ec = [True, True, True, True, True, True, True, True, True, True,
True, False, True, True]
- c = setmember1d_nu(a, b)
+ c = in1d(a, b)
assert_array_equal(c, ec)
a = np.array([5, 7, 1, 2])
b = np.array([2, 4, 3, 1, 5])
ec = np.array([True, False, True, True])
- c = setmember1d_nu(a, b)
+ c = in1d(a, b)
assert_array_equal(c, ec)
a = np.array([5, 7, 1, 1, 2])
b = np.array([2, 4, 3, 3, 1, 5])
ec = np.array([True, False, True, True, True])
- c = setmember1d_nu(a, b)
+ c = in1d(a, b)
assert_array_equal(c, ec)
a = np.array([5])
b = np.array([2])
ec = np.array([False])
- c = setmember1d_nu(a, b)
+ c = in1d(a, b)
assert_array_equal(c, ec)
a = np.array([5, 5])
b = np.array([2, 2])
ec = np.array([False, False])
- c = setmember1d_nu(a, b)
+ c = in1d(a, b)
assert_array_equal(c, ec)
- assert_array_equal(setmember1d_nu([], []), [])
+ assert_array_equal(in1d([], []), [])
+
+ def test_in1d_char_array( self ):
+ a = np.array(['a', 'b', 'c','d','e','c','e','b'])
+ b = np.array(['a','c'])
+
+ ec = np.array([True, False, True, False, False, True, False, False])
+ c = in1d(a, b)
+
+ assert_array_equal(c, ec)
def test_union1d( self ):
a = np.array( [5, 4, 7, 1, 2] )
@@ -180,14 +231,6 @@ class TestAso(TestCase):
assert_array_equal(setdiff1d(a,b),np.array(['c']))
def test_manyways( self ):
- nItem = 100
- a = np.fix( nItem / 10 * np.random.random( nItem ) )
- b = np.fix( nItem / 10 * np.random.random( nItem ) )
-
- c1 = intersect1d_nu( a, b )
- c2 = unique1d( intersect1d( a, b ) )
- assert_array_equal( c1, c2 )
-
a = np.array( [5, 7, 1, 2, 8] )
b = np.array( [9, 8, 2, 4, 3, 1, 5] )
diff --git a/numpy/ma/extras.py b/numpy/ma/extras.py
index 4454781c3..6041b7e2c 100644
--- a/numpy/ma/extras.py
+++ b/numpy/ma/extras.py
@@ -19,14 +19,14 @@ __all__ = ['apply_along_axis', 'atleast_1d', 'atleast_2d', 'atleast_3d',
'ediff1d',
'flatnotmasked_contiguous', 'flatnotmasked_edges',
'hsplit', 'hstack',
- 'intersect1d', 'intersect1d_nu',
+ 'in1d', 'intersect1d', 'intersect1d_nu',
'mask_cols', 'mask_rowcols', 'mask_rows', 'masked_all',
'masked_all_like', 'median', 'mr_',
'notmasked_contiguous', 'notmasked_edges',
'polyfit',
'row_stack',
'setdiff1d', 'setmember1d', 'setxor1d',
- 'unique1d', 'union1d',
+ 'unique', 'unique1d', 'union1d',
'vander', 'vstack',
]
@@ -45,6 +45,8 @@ import numpy.core.umath as umath
from numpy.lib.index_tricks import AxisConcatenator
from numpy.linalg import lstsq
+from numpy.lib.utils import deprecate_with_doc
+
#...............................................................................
def issequence(seq):
"""Is seq a sequence (ndarray, list or tuple)?"""
@@ -867,7 +869,7 @@ def ediff1d(arr, to_end=None, to_begin=None):
return ed
-def unique1d(ar1, return_index=False, return_inverse=False):
+def unique(ar1, return_index=False, return_inverse=False):
"""
Finds the unique elements of an array.
@@ -877,11 +879,11 @@ def unique1d(ar1, return_index=False, return_inverse=False):
See Also
--------
- np.unique1d : equivalent function for ndarrays.
+ np.unique : equivalent function for ndarrays.
"""
- output = np.unique1d(ar1,
- return_index=return_index,
- return_inverse=return_inverse)
+ output = np.unique(ar1,
+ return_index=return_index,
+ return_inverse=return_inverse)
if isinstance(output, tuple):
output = list(output)
output[0] = output[0].view(MaskedArray)
@@ -891,33 +893,7 @@ def unique1d(ar1, return_index=False, return_inverse=False):
return output
-def intersect1d(ar1, ar2):
- """
- Returns the repeated or unique elements belonging to the two arrays.
-
- Masked values are assumed equals one to the other.
- The output is always a masked array
-
- See Also
- --------
- numpy.intersect1d : equivalent function for ndarrays.
-
- Examples
- --------
- >>> x = array([1, 3, 3, 3], mask=[0, 0, 0, 1])
- >>> y = array([3, 1, 1, 1], mask=[0, 0, 0, 1])
- >>> intersect1d(x, y)
- masked_array(data = [1 1 3 3 --],
- mask = [False False False False True],
- fill_value = 999999)
- """
- aux = ma.concatenate((ar1,ar2))
- aux.sort()
- return aux[aux[1:] == aux[:-1]]
-
-
-
-def intersect1d_nu(ar1, ar2):
+def intersect1d(ar1, ar2, assume_unique=False):
"""
Returns the unique elements common to both arrays.
@@ -926,27 +902,28 @@ def intersect1d_nu(ar1, ar2):
See Also
--------
- intersect1d : Returns repeated or unique common elements.
- numpy.intersect1d_nu : equivalent function for ndarrays.
+ numpy.intersect1d : equivalent function for ndarrays.
Examples
--------
>>> x = array([1, 3, 3, 3], mask=[0, 0, 0, 1])
>>> y = array([3, 1, 1, 1], mask=[0, 0, 0, 1])
- >>> intersect1d_nu(x, y)
+ >>> intersect1d(x, y)
masked_array(data = [1 3 --],
mask = [False False True],
fill_value = 999999)
"""
- # Might be faster than unique1d( intersect1d( ar1, ar2 ) )?
- aux = ma.concatenate((unique1d(ar1), unique1d(ar2)))
+ if assume_unique:
+ aux = ma.concatenate((ar1, ar2))
+ else:
+ # Might be faster than unique1d( intersect1d( ar1, ar2 ) )?
+ aux = ma.concatenate((unique(ar1), unique(ar2)))
aux.sort()
return aux[aux[1:] == aux[:-1]]
-
-def setxor1d(ar1, ar2):
+def setxor1d(ar1, ar2, assume_unique=False):
"""
Set exclusive-or of 1D arrays with unique elements.
@@ -955,6 +932,10 @@ def setxor1d(ar1, ar2):
numpy.setxor1d : equivalent function for ndarrays
"""
+ if not assume_unique:
+ ar1 = unique(ar1)
+ ar2 = unique(ar2)
+
aux = ma.concatenate((ar1, ar2))
if aux.size == 0:
return aux
@@ -966,54 +947,52 @@ def setxor1d(ar1, ar2):
flag2 = (flag[1:] == flag[:-1])
return aux[flag2]
-
-def setmember1d(ar1, ar2):
+def in1d(ar1, ar2, assume_unique=False):
"""
- Return a boolean array set True where first element is in second array.
+ Test whether each element of an array is also present in a second
+ array.
See Also
--------
- numpy.setmember1d : equivalent function for ndarrays.
-
- """
- ar1 = ma.asanyarray(ar1)
- ar2 = ma.asanyarray( ar2 )
- ar = ma.concatenate((ar1, ar2 ))
- b1 = ma.zeros(ar1.shape, dtype = np.int8)
- b2 = ma.ones(ar2.shape, dtype = np.int8)
- tt = ma.concatenate((b1, b2))
+ numpy.in1d : equivalent function for ndarrays
- # We need this to be a stable sort, so always use 'mergesort' here. The
- # values from the first array should always come before the values from the
- # second array.
- perm = ar.argsort(kind='mergesort')
- aux = ar[perm]
- aux2 = tt[perm]
-# flag = ediff1d( aux, 1 ) == 0
- flag = ma.concatenate((aux[1:] == aux[:-1], [False]))
- ii = ma.where( flag * aux2 )[0]
- aux = perm[ii+1]
- perm[ii+1] = perm[ii]
- perm[ii] = aux
- #
- indx = perm.argsort(kind='mergesort')[:len( ar1 )]
- #
- return flag[indx]
+ Notes
+ -----
+ .. versionadded:: 1.4.0
+ """
+ if not assume_unique:
+ ar1, rev_idx = unique(ar1, return_inverse=True)
+ ar2 = unique(ar2)
+
+ ar = ma.concatenate( (ar1, ar2) )
+ # We need this to be a stable sort, so always use 'mergesort'
+ # here. The values from the first array should always come before
+ # the values from the second array.
+ order = ar.argsort(kind='mergesort')
+ sar = ar[order]
+ equal_adj = (sar[1:] == sar[:-1])
+ flag = ma.concatenate( (equal_adj, [False] ) )
+ indx = order.argsort(kind='mergesort')[:len( ar1 )]
+
+ if assume_unique:
+ return flag[indx]
+ else:
+ return flag[indx][rev_idx]
def union1d(ar1, ar2):
"""
- Union of 1D arrays with unique elements.
+ Union of two arrays.
See also
--------
numpy.union1d : equivalent function for ndarrays.
"""
- return unique1d(ma.concatenate((ar1, ar2)))
+ return unique(ma.concatenate((ar1, ar2)))
-def setdiff1d(ar1, ar2):
+def setdiff1d(ar1, ar2, assume_unique=False):
"""
Set difference of 1D arrays with unique elements.
@@ -1022,12 +1001,60 @@ def setdiff1d(ar1, ar2):
numpy.setdiff1d : equivalent function for ndarrays
"""
- aux = setmember1d(ar1,ar2)
+ aux = in1d(ar1, ar2, assume_unique=assume_unique)
if aux.size == 0:
return aux
else:
return ma.asarray(ar1)[aux == 0]
+@deprecate_with_doc('')
+def unique1d(ar1, return_index=False, return_inverse=False):
+ """ This function is deprecated. Use ma.unique() instead. """
+ output = np.unique1d(ar1,
+ return_index=return_index,
+ return_inverse=return_inverse)
+ if isinstance(output, tuple):
+ output = list(output)
+ output[0] = output[0].view(MaskedArray)
+ output = tuple(output)
+ else:
+ output = output.view(MaskedArray)
+ return output
+
+@deprecate_with_doc('')
+def intersect1d_nu(ar1, ar2):
+ """ This function is deprecated. Use ma.intersect1d() instead."""
+ # Might be faster than unique1d( intersect1d( ar1, ar2 ) )?
+ aux = ma.concatenate((unique1d(ar1), unique1d(ar2)))
+ aux.sort()
+ return aux[aux[1:] == aux[:-1]]
+
+@deprecate_with_doc('')
+def setmember1d(ar1, ar2):
+ """ This function is deprecated. Use ma.in1d() instead."""
+ ar1 = ma.asanyarray(ar1)
+ ar2 = ma.asanyarray( ar2 )
+ ar = ma.concatenate((ar1, ar2 ))
+ b1 = ma.zeros(ar1.shape, dtype = np.int8)
+ b2 = ma.ones(ar2.shape, dtype = np.int8)
+ tt = ma.concatenate((b1, b2))
+
+ # We need this to be a stable sort, so always use 'mergesort' here. The
+ # values from the first array should always come before the values from the
+ # second array.
+ perm = ar.argsort(kind='mergesort')
+ aux = ar[perm]
+ aux2 = tt[perm]
+# flag = ediff1d( aux, 1 ) == 0
+ flag = ma.concatenate((aux[1:] == aux[:-1], [False]))
+ ii = ma.where( flag * aux2 )[0]
+ aux = perm[ii+1]
+ perm[ii+1] = perm[ii]
+ perm[ii] = aux
+ #
+ indx = perm.argsort(kind='mergesort')[:len( ar1 )]
+ #
+ return flag[indx]
#####--------------------------------------------------------------------------
diff --git a/numpy/ma/tests/test_extras.py b/numpy/ma/tests/test_extras.py
index 3c6de62be..089a4e58a 100644
--- a/numpy/ma/tests/test_extras.py
+++ b/numpy/ma/tests/test_extras.py
@@ -573,19 +573,19 @@ class TestPolynomial(TestCase):
class TestArraySetOps(TestCase):
#
- def test_unique1d_onlist(self):
- "Test unique1d on list"
+ def test_unique_onlist(self):
+ "Test unique on list"
data = [1, 1, 1, 2, 2, 3]
- test = unique1d(data, return_index=True, return_inverse=True)
+ test = unique(data, return_index=True, return_inverse=True)
self.failUnless(isinstance(test[0], MaskedArray))
assert_equal(test[0], masked_array([1, 2, 3], mask=[0, 0, 0]))
assert_equal(test[1], [0, 3, 5])
assert_equal(test[2], [0, 0, 0, 1, 1, 2])
- def test_unique1d_onmaskedarray(self):
- "Test unique1d on masked data w/use_mask=True"
+ def test_unique_onmaskedarray(self):
+ "Test unique on masked data w/use_mask=True"
data = masked_array([1, 1, 1, 2, 2, 3], mask=[0, 0, 1, 0, 1, 0])
- test = unique1d(data, return_index=True, return_inverse=True)
+ test = unique(data, return_index=True, return_inverse=True)
assert_equal(test[0], masked_array([1, 2, 3, -1], mask=[0, 0, 0, 1]))
assert_equal(test[1], [0, 3, 5, 2])
assert_equal(test[2], [0, 0, 3, 1, 3, 2])
@@ -593,26 +593,26 @@ class TestArraySetOps(TestCase):
data.fill_value = 3
data = masked_array([1, 1, 1, 2, 2, 3],
mask=[0, 0, 1, 0, 1, 0], fill_value=3)
- test = unique1d(data, return_index=True, return_inverse=True)
+ test = unique(data, return_index=True, return_inverse=True)
assert_equal(test[0], masked_array([1, 2, 3, -1], mask=[0, 0, 0, 1]))
assert_equal(test[1], [0, 3, 5, 2])
assert_equal(test[2], [0, 0, 3, 1, 3, 2])
- def test_unique1d_allmasked(self):
+ def test_unique_allmasked(self):
"Test all masked"
data = masked_array([1, 1, 1], mask=True)
- test = unique1d(data, return_index=True, return_inverse=True)
+ test = unique(data, return_index=True, return_inverse=True)
assert_equal(test[0], masked_array([1,], mask=[True]))
assert_equal(test[1], [0])
assert_equal(test[2], [0, 0, 0])
#
"Test masked"
data = masked
- test = unique1d(data, return_index=True, return_inverse=True)
+ test = unique(data, return_index=True, return_inverse=True)
assert_equal(test[0], masked_array(masked))
assert_equal(test[1], [0])
assert_equal(test[2], [0])
-
+
def test_ediff1d(self):
"Tests mediff1d"
x = masked_array(np.arange(5), mask=[1,0,0,0,1])
@@ -689,15 +689,6 @@ class TestArraySetOps(TestCase):
x = array([1, 3, 3, 3], mask=[0, 0, 0, 1])
y = array([3, 1, 1, 1], mask=[0, 0, 0, 1])
test = intersect1d(x, y)
- control = array([1, 1, 3, 3, -1], mask=[0, 0, 0, 0, 1])
- assert_equal(test, control)
-
-
- def test_intersect1d_nu(self):
- "Test intersect1d_nu"
- x = array([1, 3, 3, 3], mask=[0, 0, 0, 1])
- y = array([3, 1, 1, 1], mask=[0, 0, 0, 1])
- test = intersect1d_nu(x, y)
control = array([1, 3, -1], mask=[0, 0, 1])
assert_equal(test, control)
@@ -705,7 +696,7 @@ class TestArraySetOps(TestCase):
def test_setxor1d(self):
"Test setxor1d"
a = array([1, 2, 5, 7, -1], mask=[0, 0, 0, 0, 1])
- b = array([1, 2, 3, 4, 5, -1], mask=[0, 0, 0, 0, 0, -1])
+ b = array([1, 2, 3, 4, 5, -1], mask=[0, 0, 0, 0, 0, 1])
test = setxor1d(a, b)
assert_equal(test, array([3, 4, 7]))
#
@@ -729,25 +720,30 @@ class TestArraySetOps(TestCase):
assert_array_equal([], setxor1d([],[]))
- def test_setmember1d( self ):
- "Test setmember1d"
+ def test_in1d( self ):
+ "Test in1d"
a = array([1, 2, 5, 7, -1], mask=[0, 0, 0, 0, 1])
- b = array([1, 2, 3, 4, 5, -1], mask=[0, 0, 0, 0, 0, -1])
- test = setmember1d(a, b)
+ b = array([1, 2, 3, 4, 5, -1], mask=[0, 0, 0, 0, 0, 1])
+ test = in1d(a, b)
assert_equal(test, [True, True, True, False, True])
#
- assert_array_equal([], setmember1d([],[]))
+ a = array([5, 5, 2, 1, -1], mask=[0, 0, 0, 0, 1])
+ b = array([1, 5, -1], mask=[0, 0, 1])
+ test = in1d(a, b)
+ assert_equal(test, [True, True, False, True, True])
+ #
+ assert_array_equal([], in1d([],[]))
def test_union1d( self ):
"Test union1d"
- a = array([1, 2, 5, 7, -1], mask=[0, 0, 0, 0, 1])
- b = array([1, 2, 3, 4, 5, -1], mask=[0, 0, 0, 0, 0, -1])
+ a = array([1, 2, 5, 7, 5, -1], mask=[0, 0, 0, 0, 0, 1])
+ b = array([1, 2, 3, 4, 5, -1], mask=[0, 0, 0, 0, 0, 1])
test = union1d(a, b)
control = array([1, 2, 3, 4, 5, 7, -1], mask=[0, 0, 0, 0, 0, 0, 1])
assert_equal(test, control)
#
- assert_array_equal([], setmember1d([],[]))
+ assert_array_equal([], union1d([],[]))
def test_setdiff1d( self ):
@@ -769,8 +765,6 @@ class TestArraySetOps(TestCase):
assert_array_equal(setdiff1d(a,b), np.array(['c']))
-
-
class TestShapeBase(TestCase):
#
def test_atleast1d(self):