From 4141e24fc201f8cf76180ca69eaa2d89eafaee58 Mon Sep 17 00:00:00 2001 From: Stephan Hoyer Date: Mon, 8 Oct 2018 12:52:55 -0700 Subject: ENH: __array_function__ for np.lib, part 1 np.lib.arraypad through np.lib.nanfunctions --- numpy/lib/arraysetops.py | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) (limited to 'numpy/lib/arraysetops.py') diff --git a/numpy/lib/arraysetops.py b/numpy/lib/arraysetops.py index 62e9b6d50..2f8c07114 100644 --- a/numpy/lib/arraysetops.py +++ b/numpy/lib/arraysetops.py @@ -28,6 +28,7 @@ To do: Optionally return indices analogously to unique for all functions. from __future__ import division, absolute_import, print_function import numpy as np +from numpy.core.overrides import array_function_dispatch __all__ = [ @@ -36,6 +37,11 @@ __all__ = [ ] +def _ediff1d_dispatcher(ary, to_end=None, to_begin=None): + return (ary, to_end, to_begin) + + +@array_function_dispatch(_ediff1d_dispatcher) def ediff1d(ary, to_end=None, to_begin=None): """ The differences between consecutive elements of an array. @@ -133,6 +139,12 @@ def _unpack_tuple(x): return x +def _unique_dispatcher(ar, return_index=None, return_inverse=None, + return_counts=None, axis=None): + return (ar,) + + +@array_function_dispatch(_unique_dispatcher) def unique(ar, return_index=False, return_inverse=False, return_counts=False, axis=None): """ @@ -313,6 +325,12 @@ def _unique1d(ar, return_index=False, return_inverse=False, return ret +def _intersect1d_dispatcher( + ar1, ar2, assume_unique=None, return_indices=None): + return (ar1, ar2) + + +@array_function_dispatch(_intersect1d_dispatcher) def intersect1d(ar1, ar2, assume_unique=False, return_indices=False): """ Find the intersection of two arrays. @@ -408,6 +426,11 @@ def intersect1d(ar1, ar2, assume_unique=False, return_indices=False): return int1d +def _setxor1d_dispatcher(ar1, ar2, assume_unique=None): + return (ar1, ar2) + + +@array_function_dispatch(_setxor1d_dispatcher) def setxor1d(ar1, ar2, assume_unique=False): """ Find the set exclusive-or of two arrays. @@ -562,6 +585,11 @@ def in1d(ar1, ar2, assume_unique=False, invert=False): return ret[rev_idx] +def _isin_dispatcher(element, test_elements, assume_unique=None, invert=None): + return (element, test_elements) + + +@array_function_dispatch(_isin_dispatcher) def isin(element, test_elements, assume_unique=False, invert=False): """ Calculates `element in test_elements`, broadcasting over `element` only. @@ -660,6 +688,11 @@ def isin(element, test_elements, assume_unique=False, invert=False): invert=invert).reshape(element.shape) +def _union1d_dispatcher(ar1, ar2): + return (ar1, ar2) + + +@array_function_dispatch(_union1d_dispatcher) def union1d(ar1, ar2): """ Find the union of two arrays. @@ -695,6 +728,12 @@ def union1d(ar1, ar2): """ return unique(np.concatenate((ar1, ar2), axis=None)) + +def _setdiff1d_dispatcher(ar1, ar2, assume_unique=None): + return (ar1, ar2) + + +@array_function_dispatch(_setdiff1d_dispatcher) def setdiff1d(ar1, ar2, assume_unique=False): """ Find the set difference of two arrays. -- cgit v1.2.1 From 2ddba2a474a673131c67d011cfcb76a47b869072 Mon Sep 17 00:00:00 2001 From: Tyler Reddy Date: Fri, 12 Oct 2018 07:30:05 -0700 Subject: DOC, TST: test setdiff1d assume_unique * add unit test for setdiff1d covering code path where assume_unique is True * remove setdiff1d docstring guarantee that returned value is sorted -- it is not --- numpy/lib/arraysetops.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'numpy/lib/arraysetops.py') diff --git a/numpy/lib/arraysetops.py b/numpy/lib/arraysetops.py index 2f8c07114..ec62cd7a6 100644 --- a/numpy/lib/arraysetops.py +++ b/numpy/lib/arraysetops.py @@ -738,7 +738,7 @@ def setdiff1d(ar1, ar2, assume_unique=False): """ Find the set difference of two arrays. - Return the sorted, unique values in `ar1` that are not in `ar2`. + Return the unique values in `ar1` that are not in `ar2`. Parameters ---------- @@ -753,7 +753,9 @@ def setdiff1d(ar1, ar2, assume_unique=False): Returns ------- setdiff1d : ndarray - Sorted 1D array of values in `ar1` that are not in `ar2`. + 1D array of values in `ar1` that are not in `ar2`. The result + is sorted when `assume_unique=False`, but otherwise only sorted + if the input is sorted. See Also -------- -- cgit v1.2.1 From 8bab96faf2cb740536712e49e92e133626087018 Mon Sep 17 00:00:00 2001 From: Stephan Hoyer Date: Tue, 23 Oct 2018 07:53:58 -0700 Subject: MAINT: set preferred __module__ for numpy functions --- numpy/lib/arraysetops.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'numpy/lib/arraysetops.py') diff --git a/numpy/lib/arraysetops.py b/numpy/lib/arraysetops.py index ec62cd7a6..850e20123 100644 --- a/numpy/lib/arraysetops.py +++ b/numpy/lib/arraysetops.py @@ -27,8 +27,14 @@ To do: Optionally return indices analogously to unique for all functions. """ from __future__ import division, absolute_import, print_function +import functools + import numpy as np -from numpy.core.overrides import array_function_dispatch +from numpy.core import overrides + + +array_function_dispatch = functools.partial( + overrides.array_function_dispatch, module='numpy') __all__ = [ -- cgit v1.2.1 From 4d24bbda32d133d51940b0691bd9b428d4198eaa Mon Sep 17 00:00:00 2001 From: Stephan Hoyer Date: Tue, 13 Nov 2018 09:38:07 -0800 Subject: ENH: set correct __module__ for objects in numpy's public API Fixes GH-12271 Tests verify that everything in ``dir(numpy)`` either has ``__module__`` set to ``'numpy'``, or appears in an explicit whitelist of undocumented functions and exported bulitins. These should eventually be documented or removed. I also identified a handful of functions for which I had accidentally not setup dispatch for with ``__array_function__`` before, because they were listed under "ndarray methods" in ``_add_newdocs.py``. I guess that should be a lesson in trusting code comments :). --- numpy/lib/arraysetops.py | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'numpy/lib/arraysetops.py') diff --git a/numpy/lib/arraysetops.py b/numpy/lib/arraysetops.py index 850e20123..fd64ecbd6 100644 --- a/numpy/lib/arraysetops.py +++ b/numpy/lib/arraysetops.py @@ -479,6 +479,11 @@ def setxor1d(ar1, ar2, assume_unique=False): return aux[flag[1:] & flag[:-1]] +def _in1d_dispatcher(ar1, ar2, assume_unique=None, invert=None): + return (ar1, ar2) + + +@array_function_dispatch(_in1d_dispatcher) 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. -- cgit v1.2.1 From 250861059b106371cb232456eeccd6d9e97d8f00 Mon Sep 17 00:00:00 2001 From: Tyler Reddy Date: Wed, 14 Nov 2018 11:36:59 -0800 Subject: TST, DOC: enable refguide_check * ported the refguide_check module from SciPy for usage in NumPy docstring execution/ verification; added the refguide_check run to Azure Mac OS CI * adjusted NumPy docstrings such that refguide_check passes --- numpy/lib/arraysetops.py | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) (limited to 'numpy/lib/arraysetops.py') diff --git a/numpy/lib/arraysetops.py b/numpy/lib/arraysetops.py index fd64ecbd6..558150e48 100644 --- a/numpy/lib/arraysetops.py +++ b/numpy/lib/arraysetops.py @@ -82,7 +82,7 @@ def ediff1d(ary, to_end=None, to_begin=None): 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]) + array([-99, 1, 2, ..., -7, 88, 99]) The returned array is always 1D. @@ -241,13 +241,11 @@ def unique(ar, return_index=False, return_inverse=False, >>> a = np.array(['a', 'b', 'b', 'c', 'a']) >>> u, indices = np.unique(a, return_index=True) >>> u - array(['a', 'b', 'c'], - dtype='|S1') + array(['a', 'b', 'c'], dtype='>> indices array([0, 1, 3]) >>> a[indices] - array(['a', 'b', 'c'], - dtype='|S1') + array(['a', 'b', 'c'], dtype='>> u array([1, 2, 3, 4, 6]) >>> indices - array([0, 1, 4, 3, 1, 2, 1]) + array([0, 1, 4, ..., 1, 2, 1]) >>> u[indices] - array([1, 2, 6, 4, 2, 3, 2]) + array([1, 2, 6, ..., 2, 3, 2]) """ ar = np.asanyarray(ar) @@ -661,8 +659,8 @@ def isin(element, test_elements, assume_unique=False, invert=False): >>> test_elements = [1, 2, 4, 8] >>> mask = np.isin(element, test_elements) >>> mask - array([[ False, True], - [ True, False]]) + array([[False, True], + [ True, False]]) >>> element[mask] array([2, 4]) @@ -676,7 +674,7 @@ def isin(element, test_elements, assume_unique=False, invert=False): >>> mask = np.isin(element, test_elements, invert=True) >>> mask array([[ True, False], - [ False, True]]) + [False, True]]) >>> element[mask] array([0, 6]) @@ -685,14 +683,14 @@ def isin(element, test_elements, assume_unique=False, invert=False): >>> test_set = {1, 2, 4, 8} >>> np.isin(element, test_set) - array([[ False, False], - [ False, False]]) + array([[False, False], + [False, False]]) Casting the set to a list gives the expected result: >>> np.isin(element, list(test_set)) - array([[ False, True], - [ True, False]]) + array([[False, True], + [ True, False]]) """ element = np.asarray(element) return in1d(element, test_elements, assume_unique=assume_unique, -- cgit v1.2.1 From c088383cb290ca064d456e89d79177a0e234cb8d Mon Sep 17 00:00:00 2001 From: mattip Date: Thu, 10 Jan 2019 12:16:16 +0200 Subject: BUG: loosen kwargs requirements in ediff1d --- numpy/lib/arraysetops.py | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) (limited to 'numpy/lib/arraysetops.py') diff --git a/numpy/lib/arraysetops.py b/numpy/lib/arraysetops.py index 558150e48..b53d8c03f 100644 --- a/numpy/lib/arraysetops.py +++ b/numpy/lib/arraysetops.py @@ -94,8 +94,7 @@ def ediff1d(ary, to_end=None, to_begin=None): # force a 1d array ary = np.asanyarray(ary).ravel() - # we have unit tests enforcing - # propagation of the dtype of input + # enforce propagation of the dtype of input # ary to returned result dtype_req = ary.dtype @@ -106,23 +105,22 @@ def ediff1d(ary, to_end=None, to_begin=None): if to_begin is None: l_begin = 0 else: - to_begin = np.asanyarray(to_begin) - if not np.can_cast(to_begin, dtype_req): - raise TypeError("dtype of to_begin must be compatible " - "with input ary") - - to_begin = to_begin.ravel() + _to_begin = np.asanyarray(to_begin, dtype=dtype_req) + if not np.all(_to_begin == to_begin): + raise ValueError("cannot convert 'to_begin' to array with dtype " + "'%r' as required for input ary" % dtype_req) + to_begin = _to_begin.ravel() l_begin = len(to_begin) if to_end is None: l_end = 0 else: - to_end = np.asanyarray(to_end) - if not np.can_cast(to_end, dtype_req): - raise TypeError("dtype of to_end must be compatible " - "with input ary") - - to_end = to_end.ravel() + _to_end = np.asanyarray(to_end, dtype=dtype_req) + # check that casting has not overflowed + if not np.all(_to_end == to_end): + raise ValueError("cannot convert 'to_end' to array with dtype " + "'%r' as required for input ary" % dtype_req) + to_end = _to_end.ravel() l_end = len(to_end) # do the calculation in place and copy to_begin and to_end -- cgit v1.2.1 From 7329c8ceb4eee9a31f35cb50af14c8f4c71639ff Mon Sep 17 00:00:00 2001 From: Jackie Leng Date: Tue, 23 Jul 2019 13:10:49 +0200 Subject: Add blank line above doctest for intersect1d --- numpy/lib/arraysetops.py | 1 + 1 file changed, 1 insertion(+) (limited to 'numpy/lib/arraysetops.py') diff --git a/numpy/lib/arraysetops.py b/numpy/lib/arraysetops.py index b53d8c03f..f3f4bc17e 100644 --- a/numpy/lib/arraysetops.py +++ b/numpy/lib/arraysetops.py @@ -383,6 +383,7 @@ def intersect1d(ar1, ar2, assume_unique=False, return_indices=False): To return the indices of the values common to the input arrays along with the intersected values: + >>> x = np.array([1, 1, 2, 3, 4]) >>> y = np.array([2, 1, 4, 6]) >>> xy, x_ind, y_ind = np.intersect1d(x, y, return_indices=True) -- cgit v1.2.1 From 3b3eaa60dc31677d1b19cb49e5c414d41ac4089a Mon Sep 17 00:00:00 2001 From: "Huang, Guangtai" Date: Mon, 12 Aug 2019 12:34:01 +0800 Subject: fix unique --- numpy/lib/arraysetops.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'numpy/lib/arraysetops.py') diff --git a/numpy/lib/arraysetops.py b/numpy/lib/arraysetops.py index f3f4bc17e..c3e833f74 100644 --- a/numpy/lib/arraysetops.py +++ b/numpy/lib/arraysetops.py @@ -264,7 +264,7 @@ def unique(ar, return_index=False, return_inverse=False, # axis was specified and not None try: - ar = np.swapaxes(ar, axis, 0) + ar = np.moveaxis(ar, axis, 0) except np.AxisError: # this removes the "axis1" or "axis2" prefix from the error message raise np.AxisError(axis, ar.ndim) @@ -285,7 +285,7 @@ def unique(ar, return_index=False, return_inverse=False, def reshape_uniq(uniq): uniq = uniq.view(orig_dtype) uniq = uniq.reshape(-1, *orig_shape[1:]) - uniq = np.swapaxes(uniq, 0, axis) + uniq = np.moveaxis(uniq, 0, axis) return uniq output = _unique1d(consolidated, return_index, -- cgit v1.2.1 From 0df57515070ed11020feb1e5f1fa88112ee5e09e Mon Sep 17 00:00:00 2001 From: "Huang, Guangtai" Date: Wed, 21 Aug 2019 11:04:38 +0800 Subject: add description in docstring --- numpy/lib/arraysetops.py | 1 + 1 file changed, 1 insertion(+) (limited to 'numpy/lib/arraysetops.py') diff --git a/numpy/lib/arraysetops.py b/numpy/lib/arraysetops.py index c3e833f74..2309f7e42 100644 --- a/numpy/lib/arraysetops.py +++ b/numpy/lib/arraysetops.py @@ -213,6 +213,7 @@ def unique(ar, return_index=False, return_inverse=False, ----- When an axis is specified the subarrays indexed by the axis are sorted. This is done by making the specified axis the first dimension of the array + (move the axis to the first dimension to keep the order of the other axes) and then flattening the subarrays in C order. The flattened subarrays are then viewed as a structured type with each element given a label, with the effect that we end up with a 1-D array of structured types that can be -- cgit v1.2.1