-
-
Notifications
You must be signed in to change notification settings - Fork 11.1k
Adding isin function for multidimensional arrays #8423
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 17 commits
17faf5a
34a40da
2b4a81b
db5e5fd
f63cf31
a9bce34
f06ed40
0938763
e10ee1e
0ec089a
ba10c98
e72b686
818337d
6ace52e
7712179
a2c9b6c
552a193
fa0b0be
0ff6be4
545df63
41e5b0b
521d517
8805bbb
4d3f67c
0395f39
3d809a6
d22cafc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,6 +17,7 @@ Boolean operations | |
|
||
in1d | ||
intersect1d | ||
isin | ||
setdiff1d | ||
setxor1d | ||
union1d |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,10 @@ | ||
""" | ||
Set operations for 1D numeric arrays based on sorting. | ||
Set operations for arrays based on sorting. | ||
|
||
:Contains: | ||
ediff1d, | ||
unique, | ||
isin, | ||
ediff1d, | ||
intersect1d, | ||
setxor1d, | ||
in1d, | ||
|
@@ -31,7 +32,7 @@ | |
|
||
__all__ = [ | ||
'ediff1d', 'intersect1d', 'setxor1d', 'union1d', 'setdiff1d', 'unique', | ||
'in1d' | ||
'in1d', 'isin' | ||
] | ||
|
||
|
||
|
@@ -380,13 +381,18 @@ def setxor1d(ar1, ar2, assume_unique=False): | |
flag2 = flag[1:] == flag[:-1] | ||
return aux[flag2] | ||
|
||
|
||
def in1d(ar1, ar2, assume_unique=False, invert=False): | ||
""" | ||
Test whether each element of a 1-D 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 in `ar2` and False otherwise. | ||
|
||
This function has been deprecated: use `isin` instead. | ||
|
||
Deprecated since version 1.13.0. | ||
|
||
Parameters | ||
---------- | ||
ar1 : (M,) array_like | ||
|
@@ -411,6 +417,8 @@ def in1d(ar1, ar2, assume_unique=False, invert=False): | |
|
||
See Also | ||
-------- | ||
isin : Version of this function that preserves the | ||
shape of ar1. | ||
numpy.lib.arraysetops : Module with a number of other functions for | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "See also: The module you're looking at right now" is a little weird. @brsr, you don't need to worry about it in this PR though. |
||
performing set operations on arrays. | ||
|
||
|
@@ -481,6 +489,76 @@ def in1d(ar1, ar2, assume_unique=False, invert=False): | |
else: | ||
return ret[rev_idx] | ||
|
||
|
||
def isin(element, test_elements, assume_unique=False, invert=False): | ||
""" | ||
Calculates `element in test_elements`, broadcasting over `element` only. | ||
Returns a boolean array of the same shape as `elements` that is True | ||
where an element of `elements` is in `test_elements` and False otherwise. | ||
|
||
Parameters | ||
---------- | ||
element : array_like | ||
Input array. | ||
test_elements : array_like | ||
The values against which to test each value of `elements`. | ||
This argument is flattened if it is an array or array_like. | ||
See notes for behavior with non-array-like parameters. | ||
assume_unique : bool, optional | ||
If True, the input arrays are both assumed to be unique, which | ||
can speed up the calculation. Default is False. | ||
invert : bool, optional | ||
If True, the values in the returned array are inverted (that is, | ||
False where an element of `ar1` is in `ar2` and True otherwise). | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These names are out of date. I'd probably ditch this wording all together, and explain it in terms of |
||
Default is False. ``np.isin(a, b, invert=True)`` is equivalent | ||
to (but is faster than) ``np.invert(np.isin(a, b))``. | ||
|
||
Returns | ||
------- | ||
isin : ndarray, bool | ||
Has the same shape as `element`. The values `elements[isin]` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missed an |
||
are in `test_elements`. | ||
|
||
See Also | ||
-------- | ||
in1d : Flattened version of this function. | ||
numpy.lib.arraysetops : Module with a number of other functions for | ||
performing set operations on arrays. | ||
Notes | ||
----- | ||
|
||
`isin` is an element-wise function version of the python keyword `in`. | ||
``isin(a, b)`` is roughly equivalent to | ||
``np.array([item in b for item in a])`` if `a` and `b` are 1-D sequences. | ||
|
||
If `test_elements` is a set (or other non-sequence collection) it will | ||
be converted to an object array with one element, rather than an array | ||
of the values contained in `test_elements`. Converting the set to | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Probably worth pointing out that this is just the |
||
a list usually gives the desired behavior. | ||
|
||
.. versionadded:: 1.13.0 | ||
|
||
Examples | ||
-------- | ||
>>> element = np.array([[0, 2], [4, 6]]) | ||
>>> test_elements = [1, 2, 4, 8] | ||
>>> mask = np.isin(element, test_elements) | ||
>>> mask | ||
array([[ False, True], | ||
[ True, False]], dtype=bool) | ||
>>> element[mask] | ||
array([2, 4]) | ||
>>> mask = np.isin(element, test_elements, invert=True) | ||
>>> mask | ||
array([[ True, False], | ||
[ False, True]], dtype=bool) | ||
>>> element[mask] | ||
array([0, 6])""" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: needs an extra newline in this docstring |
||
element = np.array(element) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should be |
||
return in1d(element, test_elements, assume_unique=assume_unique, | ||
invert=invert).reshape(element.shape) | ||
|
||
|
||
def union1d(ar1, ar2): | ||
""" | ||
Find the union of two arrays. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -147,6 +147,8 @@ | |
setxor1d Set exclusive-or of 1D arrays with unique elements. | ||
in1d Test whether elements in a 1D array are also present in | ||
another array. | ||
isin Test whether elements in an array are also present in | ||
another array, preserving shape of first array. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe "test whether each element of one array is present anywhere within another"? No strong feelings here |
||
union1d Union of 1D arrays with unique elements. | ||
setdiff1d Set difference of 1D arrays with unique elements. | ||
================ =================== | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,7 +8,7 @@ | |
run_module_suite, TestCase, assert_array_equal, assert_equal, assert_raises | ||
) | ||
from numpy.lib.arraysetops import ( | ||
ediff1d, intersect1d, setxor1d, union1d, setdiff1d, unique, in1d | ||
ediff1d, intersect1d, setxor1d, union1d, setdiff1d, unique, in1d, isin | ||
) | ||
|
||
|
||
|
@@ -77,6 +77,23 @@ def test_ediff1d(self): | |
assert(isinstance(ediff1d(np.matrix(1)), np.matrix)) | ||
assert(isinstance(ediff1d(np.matrix(1), to_begin=1), np.matrix)) | ||
|
||
def test_isin(self): | ||
# the tests for in1d cover most of isin's behavior | ||
# if in1d is deprecated, would need to change those tests to test | ||
# isin instead. | ||
a = np.arange(24).reshape([2, 3, 4]) | ||
b = [0, 10, 20, 30, 1, 3, 11, 22, 33] | ||
ec = np.zeros((2, 3, 4), dtype=bool) | ||
ec[0, 0, 0] = True | ||
ec[0, 0, 1] = True | ||
ec[0, 0, 3] = True | ||
ec[0, 2, 2] = True | ||
ec[0, 2, 3] = True | ||
ec[1, 2, 0] = True | ||
ec[1, 2, 2] = True | ||
c = isin(a, b) | ||
assert_array_equal(c, ec) | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Needs a test for 0d |
||
def test_in1d(self): | ||
# we use two different sizes for the b array here to test the | ||
# two different paths in in1d(). | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,7 +16,7 @@ | |
'column_stack', 'compress_cols', 'compress_nd', 'compress_rowcols', | ||
'compress_rows', 'count_masked', 'corrcoef', 'cov', 'diagflat', 'dot', | ||
'dstack', 'ediff1d', 'flatnotmasked_contiguous', 'flatnotmasked_edges', | ||
'hsplit', 'hstack', 'in1d', 'intersect1d', 'mask_cols', 'mask_rowcols', | ||
'hsplit', 'hstack', 'isin', 'in1d', 'intersect1d', 'mask_cols', 'mask_rowcols', | ||
'mask_rows', 'masked_all', 'masked_all_like', 'median', 'mr_', | ||
'notmasked_contiguous', 'notmasked_edges', 'polyfit', 'row_stack', | ||
'setdiff1d', 'setxor1d', 'unique', 'union1d', 'vander', 'vstack', | ||
|
@@ -1137,15 +1137,22 @@ def setxor1d(ar1, ar2, assume_unique=False): | |
flag2 = (flag[1:] == flag[:-1]) | ||
return aux[flag2] | ||
|
||
|
||
def in1d(ar1, ar2, assume_unique=False, invert=False): | ||
""" | ||
Test whether each element of an array is also present in a second | ||
array. | ||
|
||
The output is always a masked array. See `numpy.in1d` for more details. | ||
|
||
This function has been deprecated: use `isin` instead. | ||
|
||
Deprecated since version 1.13.0. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should use the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For what it's worth, numpy/HOWTO_DOCUMENT.rst.txt says something different about deprecation warnings. |
||
|
||
|
||
See Also | ||
-------- | ||
isin : Version of this function that preserves the shape of ar1. | ||
numpy.in1d : Equivalent function for ndarrays. | ||
|
||
Notes | ||
|
@@ -1176,6 +1183,29 @@ def in1d(ar1, ar2, assume_unique=False, invert=False): | |
return flag[indx][rev_idx] | ||
|
||
|
||
def isin(element, test_elements, assume_unique=False, invert=False): | ||
""" | ||
Calculates `element in test_elements`, broadcasting over | ||
`element` only. | ||
|
||
The output is always a masked array of the same shape as `element`. | ||
See `numpy.isin` for more details. | ||
|
||
See Also | ||
-------- | ||
in1d : Flattened version of this function. | ||
numpy.isin : Equivalent function for ndarrays. | ||
|
||
Notes | ||
----- | ||
.. versionadded:: 1.13.0 | ||
|
||
""" | ||
element = ma.array(element) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Again, |
||
return in1d(element, test_elements, assume_unique=assume_unique, | ||
invert=invert).reshape(element.shape) | ||
|
||
|
||
def union1d(ar1, ar2): | ||
""" | ||
Union of two arrays. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,7 +28,7 @@ | |
median, average, unique, setxor1d, setdiff1d, union1d, intersect1d, in1d, | ||
ediff1d, apply_over_axes, apply_along_axis, compress_nd, compress_rowcols, | ||
mask_rowcols, clump_masked, clump_unmasked, flatnotmasked_contiguous, | ||
notmasked_contiguous, notmasked_edges, masked_all, masked_all_like, | ||
notmasked_contiguous, notmasked_edges, masked_all, masked_all_like, isin, | ||
diagflat | ||
) | ||
import numpy.ma.extras as mae | ||
|
@@ -1435,6 +1435,24 @@ def test_setxor1d(self): | |
# | ||
assert_array_equal([], setxor1d([], [])) | ||
|
||
def test_isin(self): | ||
# the tests for in1d cover most of isin's behavior | ||
# if in1d is deprecated, would need to change those tests to test | ||
# isin instead. | ||
a = np.arange(24).reshape([2, 3, 4]) | ||
mask = np.zeros([2, 3, 4]) | ||
mask[1, 2, 0] = 1 | ||
a = array(a, mask=mask) | ||
#masked: N Y N Y N Y N Y N | ||
b = array([0, 10, 20, 30, 1, 3, 11, 22, 33], | ||
mask=[0, 1, 0, 1, 0, 1, 0, 1, 0]) | ||
ec = zeros((2, 3, 4), dtype=bool) | ||
ec[0, 0, 0] = True | ||
ec[0, 0, 1] = True | ||
ec[0, 2, 3] = True | ||
c = isin(a, b) | ||
assert_array_equal(c, ec) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we have a test here for Also, a test of what happens if you call |
||
|
||
def test_in1d(self): | ||
# Test in1d | ||
a = array([1, 2, 5, 7, -1], mask=[0, 0, 0, 0, 1]) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here