8000 ENH: Adding keepdims to np.argmin,np.argmax by czgdp1807 · Pull Request #19211 · numpy/numpy · GitHub
[go: up one dir, main page]

Skip to content

ENH: Adding keepdims to np.argmin,np.argmax #19211

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

Merged
merged 38 commits into from
Jul 7, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
0e5817e
keepdims added to np.argmin,np.argmax
czgdp1807 Jun 10, 2021
5d66427
Added release notes entry
czgdp1807 Jun 10, 2021
4d8f3af
tested for axis=None,keepdims=True
czgdp1807 Jun 10, 2021
aa2adc9
Apply suggestions from code review
czgdp1807 Jun 10, 2021
f7d4df4
updated interface
czgdp1807 Jun 10, 2021
1e725c7
updated interface
czgdp1807 Jun 10, 2021
4d2bfab
API changed, implementation to be done
czgdp1807 Jun 10, 2021
09433d6
Added reshape approach to C implementation
czgdp1807 Jun 11, 2021
8ea07b4
buggy implementation without reshape
czgdp1807 Jun 11, 2021
aa73907
TestArgMax, TestArgMin fixed, comments added
czgdp1807 Jun 12, 2021
22fbb06
Fixed for matrix
czgdp1807 Jun 12, 2021
d04946f
removed unrequired changes
czgdp1807 Jun 12, 2021
512b359
fixed CI failure
czgdp1807 Jun 12, 2021
da3df5b
fixed linting issue
czgdp1807 Jun 12, 2021
828df3b
PyArray_ArgMaxKeepdims now only modifies shape and strides
czgdp1807 Jun 18, 2021
91e7530
Comments added to PyArray_ArgMaxKeepdims
czgdp1807 Jun 18, 2021
a1c0faa
Updated implementation of PyArray_ArgMinKeepdims to match with PyArra…
czgdp1807 Jun 18, 2021
fa5839b
Testing complete for PyArray_ArgMinKeepdims and PyArray_ArgMaxKeepdims
czgdp1807 Jun 18, 2021
2cd3ff1
PyArray_ArgMinWithKeepdims both keepdims=True and keepdims=False
czgdp1807 Jun 19, 2021
124abe3
matched implementation of PyArray_ArgMaxKeepdims and PyArray_ArgMinKe…
czgdp1807 Jun 19, 2021
6bd9f4c
simplified implementation
czgdp1807 Jun 19, 2021
55a85d3
Added missing comment
czgdp1807 Jun 19, 2021
568251e
removed unwanted header
czgdp1807 Jun 19, 2021
9260d40
addressed all the reviews
czgdp1807 Jun 21, 2021
06d9610
Removing unwanted changes
czgdp1807 Jun 21, 2021
2112709
fixed docs
czgdp1807 Jun 21, 2021
e0dd74e
Added new lines
czgdp1807 Jun 21, 2021
11d7e33
restored annotations
czgdp1807 Jun 22, 2021
eec3e2f
Merge branch 'keepdims' of https://github.com/czgdp1807/numpy into ke…
czgdp1807 Jun 22, 2021
4c9f113
parametrized test
czgdp1807 Jun 24, 2021
db9c704
Apply suggestions from code review
czgdp1807 Jun 30, 2021
11cd597
keyword handling now done in np.argmin/np.argmax
czgdp1807 Jun 30, 2021
bb906bf
corrected indendation
czgdp1807 Jun 30, 2021
3b72f59
used with pytest.riases(ValueError)
czgdp1807 Jun 30, 2021
66adc84
fixed release notes
czgdp1807 Jun 30, 2021
4be86dd
removed PyArray_ArgMaxWithKeepdims and PyArray_ArgMinWithKeepdims fro…
czgdp1807 Jul 2, 2021
8f9f108
Apply suggestions from code review
czgdp1807 Jul 2, 2021
c55aaea
Apply suggestions from code review
czgdp1807 Jul 2, 2021
File filter

Filter by extension

Filter by extension

8000 Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Added reshape approach to C implementation
  • Loading branch information
czgdp1807 committed Jun 11, 2021
commit 09433d6202f0151c382ebc9d3e997ed5a721afcd
10 changes: 8 8000 additions & 2 deletions doc/source/reference/c-api/array.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2014,12 +2014,18 @@ Calculation


.. c:function:: PyObject* PyArray_ArgMax( \
PyArrayObject* self, int axis, PyArrayObject* out, \
int keepdims)
PyArrayObject* self, int axis, PyArrayObject* out)

Equivalent to :meth:`ndarray.argmax<numpy.ndarray.argmax>` (*self*, *axis*). Return the index of
the largest element of *self* along *axis*.

.. c:function:: PyObject* PyArray_ArgMaxKeepdims( \
PyArrayObject* self, int axis, PyArrayObject* out)

Equivalent to :meth:`ndarray.argmax<numpy.ndarray.argmax>` (*self*, *axis*). Return the index of
the largest element of *self* along *axis*. The number of dimensions of the result matches with the
that of the input object.

.. c:function:: PyObject* PyArray_ArgMin( \
PyArrayObject* self, int axis, PyArrayObject* out)

Expand Down
3 changes: 2 additions & 1 deletion numpy/__init__.cython-30.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -643,7 +643,8 @@ cdef extern from "numpy/arrayobject.h":
int PyArray_Sort (ndarray, int, NPY_SORTKIND)
object PyArray_ArgSort (ndarray, int, NPY_SORTKIND)
object PyArray_SearchSorted (ndarray, object, NPY_SEARCHSIDE, PyObject *)
object PyArray_ArgMax (ndarray, int, ndarray, int)
object PyArray_ArgMax (ndarray, int, ndarray)
object PyArray_ArgMaxKeepdims (ndarray, int, ndarray)
object PyArray_ArgMin (ndarray, int, ndarray)
object PyArray_Reshape (ndarray, object)
object PyArray_Newshape (ndarray, PyArray_Dims *, NPY_ORDER)
Expand Down
3 changes: 2 additions & 1 deletion numpy/__init__.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -601,7 +601,8 @@ cdef extern from "numpy/arrayobject.h":
int PyArray_Sort (ndarray, int, NPY_SORTKIND)
object PyArray_ArgSort (ndarray, int, NPY_SORTKIND)
object PyArray_SearchSorted (ndarray, object, NPY_SEARCHSIDE, PyObject *)
object PyArray_ArgMax (ndarray, int, ndarray, int)
object PyArray_ArgMax (ndarray, int, ndarray)
object PyArray_ArgMaxKeepdims (ndarray, int, ndarray)
object PyArray_ArgMin (ndarray, int, ndarray)
object PyArray_Reshape (ndarray, object)
object PyArray_Newshape (ndarray, PyArray_Dims *, NPY_ORDER)
Expand Down
40 changes: 38 additions & 2 deletions numpy/core/src/multiarray/calculation.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
#include "calculation.h"
#include "array_assign.h"

#include "alloc.h"

static double
power_of_ten(int n)
{
Expand All @@ -38,8 +40,7 @@ power_of_ten(int n)
* ArgMax
*/
NPY_NO_EXPORT PyObject *
PyArray_ArgMax(PyArrayObject *op, int axis, PyArrayObject *out,
int keepdims)
PyArray_ArgMax(PyArrayObject *op, int axis, PyArrayObject *out)
{
PyArrayObject *ap = NULL, *rp = NULL;
PyArray_ArgFunc* arg_func;
Expand Down Expand Up @@ -151,6 +152,41 @@ PyArray_ArgMax(PyArrayObject *op, int axis, PyArrayObject *out,
return NULL;
}

NPY_NO_EXPORT PyObject*
PyArray_ArgMaxKeepdims(PyArrayObject *op, int axis, PyArrayObject* out) {
PyArrayObject* ret = (PyArrayObject*)PyArray_ArgMax(op, axis, NULL);
PyArray_Dims newdims;
newdims.len = PyArray_NDIM(op);
newdims.ptr = npy_alloc_cache_dim(newdims.len);
npy_intp* currdim = PyArray_DIMS(op);
for( int dim = 0; dim < newdims.len; dim++ ) {
if( dim == axis || axis == NPY_MAXDIMS ) {
newdims.ptr[dim] = 1;
} else {
newdims.ptr[dim] = currdim[dim];
}
}

// If ret is same as out, then should we reshape or raise an error?
ret = (PyArrayObject*)PyArray_Newshape(ret, &newdims, NPY_CORDER);
if (out != NULL) {
if ((PyArray_NDIM(out) != PyArray_NDIM(ret)) ||
!PyArray_CompareLists(PyArray_DIMS(out), PyArray_DIMS(ret),
PyArray_NDIM(out))) {
PyErr_SetString(PyExc_ValueError,
"output array dimensions do not match with that of result from np.argmax.");
Py_XDECREF(ret);
return NULL;
}
PyArray_CopyInto(out, ret);
Py_DECREF(ret);
ret = out;
Py_INCREF(ret);
}
npy_free_cache_dim_obj(newdims);
return (PyObject*)ret;
}

/*NUMPY_API
* ArgMin
*/
Expand Down
6 changes: 4 additions & 2 deletions numpy/core/src/multiarray/calculation.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
#define _NPY_CALCULATION_H_

NPY_NO_EXPORT PyObject*
PyArray_ArgMax(PyArrayObject* self, int axis, PyArrayObject *out,
int keepdims);
PyArray_ArgMax(PyArrayObject* self, int axis, PyArrayObject *out);

NPY_NO_EXPORT PyObject*
PyArray_ArgMaxKeepdims(PyArrayObject* self, int axis, PyArrayObject *out);

NPY_NO_EXPORT PyObject*
PyArray_ArgMin(PyArrayObject* self, int axis, PyArrayObject *out);
Expand Down
9 changes: 7 additions & 2 deletions numpy/core/src/multiarray/methods.c
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ array_argmax(PyArrayObject *self,
{
int axis = NPY_MAXDIMS;
PyArrayObject *out = NULL;
int keepdims = -1;
npy_bool keepdims = NPY_FALSE;
NPY_PREPARE_ARGPARSER;

if (npy_parse_arguments("argmax", args, len_args, kwnames,
Expand All @@ -295,7 +295,12 @@ array_argmax(PyArrayObject *self,
return NULL;
}

PyObject *ret = PyArray_ArgMax(self, axis, out, keepdims);
PyObject *ret;
if( keepdims ) {
ret = PyArray_ArgMaxKeepdims(self, axis, out);
} else {
ret = PyArray_ArgMax(self, axis, out);
}

/* this matches the unpacking behavior of ufuncs */
if (out == NULL) {
Expand Down
1 change: 1 addition & 0 deletions numpy/core/src/umath/ufunc_object.c
Original file line number Diff line number Diff line change
Expand Up @@ -4001,6 +4001,7 @@ static PyObject *
PyUFunc_GenericReduction(PyUFuncObject *ufunc,
PyObject *const *args, Py_ssize_t len_args, PyObject *kwnames, int operation)
{

int i, naxes=0, ndim;
int axes[NPY_MAXDIMS];

Expand Down
38 changes: 23 additions & 15 deletions numpy/core/tests/test_multiarray.py
Original file line number Diff line number Diff line change
Expand Up @@ -4344,11 +4344,18 @@ def test_np_argmax_keepdims(self):
res = np.argmax(arr, axis=axis, keepdims=True)
assert_(res.ndim == arr.ndim)
assert_(res.shape[axis] == 1)
outarray = np.empty(res.shape, dtype=res.dtype)
np.argmax(arr, axis=axis, out=outarray,
keepdims=True)
assert_equal(res, outarray)

# Testing for axis=None, keepdims=True
res = np.argmin(arr, axis=None, keepdims=True)
res = np.argmax(arr, axis=None, keepdims=True)
assert_(res.ndim == arr.ndim)
assert_(res.shape == (1,)*arr.ndim)
outarray = np.empty(res.shape, dtype=res.dtype)
np.argmax(arr, axis=None, out=outarray, keepdims=True)
assert_equal(res, outarray)

class TestArgmin:

Expand Down Expand Up @@ -4505,21 +4512,22 @@ def test_object_argmin_with_NULLs(self):
a[1] = 10
assert_equal(a.argmin(), 1)

def test_np_argmin_keepdims(self):

sizes = [(3,), (3, 2), (2, 3),
(3, 3), (2, 3, 4), (4, 3, 2)]
for size in sizes:
arr = np.random.normal(size=size)
for axis in range(len(size)):
res = np.argmin(arr, axis=axis, keepdims=True)
assert_(res.ndim == arr.ndim)
assert_(res.shape[axis] == 1) 87A2
# Avoid until np.argmin is ready to support keepdims
# def test_np_argmin_keepdims(self):

# sizes = [(3,), (3, 2), (2, 3),
# (3, 3), (2, 3, 4), (4, 3, 2)]
# for size in sizes:
# arr = np.random.normal(size=size)
# for axis in range(len(size)):
# res = np.argmin(arr, axis=axis, keepdims=True)
# assert_(res.ndim == arr.ndim)
# assert_(res.shape[axis] == 1)

# Testing for axis=None, keepdims=True
res = np.argmin(arr, axis=None, keepdims=True)
assert_(res.ndim == arr.ndim)
assert_(res.shape == (1,)*arr.ndim)
# # Testing for axis=None, keepdims=True
# res = np.argmin(arr, axis=None, keepdims=True)
# assert_(res.ndim == arr.ndim)
# assert_(res.shape == (1,)*arr.ndim)

class TestMinMax:

Expand Down
0