summaryrefslogtreecommitdiff
path: root/numpy/lib/arraysetops.py
diff options
context:
space:
mode:
authorAaron Meurer <asmeurer@gmail.com>2021-06-14 14:07:18 -0600
committerAaron Meurer <asmeurer@gmail.com>2021-06-14 14:07:18 -0600
commit8c78b84968e580f24b3705378fb35705a434cdf1 (patch)
treec9f82beeb5a2c3f0301f7984d4b6d19539c35d23 /numpy/lib/arraysetops.py
parent8bf3a4618f1de951c7a4ccdb8bc3e36825a1b744 (diff)
parent75f852edf94a7293e7982ad516bee314d7187c2d (diff)
downloadnumpy-8c78b84968e580f24b3705378fb35705a434cdf1.tar.gz
Merge branch 'main' into matrix_rank-doc-fix
Diffstat (limited to 'numpy/lib/arraysetops.py')
-rw-r--r--numpy/lib/arraysetops.py25
1 files changed, 24 insertions, 1 deletions
diff --git a/numpy/lib/arraysetops.py b/numpy/lib/arraysetops.py
index 6c6c1ff80..7600e17be 100644
--- a/numpy/lib/arraysetops.py
+++ b/numpy/lib/arraysetops.py
@@ -209,6 +209,16 @@ def unique(ar, return_index=False, return_inverse=False,
flattened subarrays are sorted in lexicographic order starting with the
first element.
+ .. versionchanged: NumPy 1.21
+ If nan values are in the input array, a single nan is put
+ to the end of the sorted unique values.
+
+ Also for complex arrays all NaN values are considered equivalent
+ (no matter whether the NaN is in the real or imaginary part).
+ As the representant for the returned array the smallest one in the
+ lexicographical order is chosen - see np.sort for how the lexicographical
+ order is defined for complex arrays.
+
Examples
--------
>>> np.unique([1, 1, 2, 2, 3, 3])
@@ -324,7 +334,16 @@ def _unique1d(ar, return_index=False, return_inverse=False,
aux = ar
mask = np.empty(aux.shape, dtype=np.bool_)
mask[:1] = True
- mask[1:] = aux[1:] != aux[:-1]
+ if aux.shape[0] > 0 and aux.dtype.kind in "cfmM" and np.isnan(aux[-1]):
+ if aux.dtype.kind == "c": # for complex all NaNs are considered equivalent
+ aux_firstnan = np.searchsorted(np.isnan(aux), True, side='left')
+ else:
+ aux_firstnan = np.searchsorted(aux, aux[-1], side='left')
+ mask[1:aux_firstnan] = (aux[1:aux_firstnan] != aux[:aux_firstnan - 1])
+ mask[aux_firstnan] = True
+ mask[aux_firstnan + 1:] = False
+ else:
+ mask[1:] = aux[1:] != aux[:-1]
ret = (aux[mask],)
if return_index:
@@ -565,6 +584,10 @@ def in1d(ar1, ar2, assume_unique=False, invert=False):
ar1 = np.asarray(ar1).ravel()
ar2 = np.asarray(ar2).ravel()
+ # Ensure that iteration through object arrays yields size-1 arrays
+ if ar2.dtype == object:
+ ar2 = ar2.reshape(-1, 1)
+
# Check if one of the arrays may contain arbitrary objects
contains_object = ar1.dtype.hasobject or ar2.dtype.hasobject