diff options
-rw-r--r-- | doc/release/2.0.0-notes.rst | 6 | ||||
-rw-r--r-- | numpy/core/src/multiarray/calculation.c | 2 | ||||
-rw-r--r-- | numpy/core/src/multiarray/scalarapi.c | 16 | ||||
-rw-r--r-- | numpy/core/src/umath/ufunc_object.c | 23 | ||||
-rw-r--r-- | numpy/core/tests/test_maskna.py | 56 |
5 files changed, 80 insertions, 23 deletions
diff --git a/doc/release/2.0.0-notes.rst b/doc/release/2.0.0-notes.rst index f36889d62..195a24d01 100644 --- a/doc/release/2.0.0-notes.rst +++ b/doc/release/2.0.0-notes.rst @@ -22,8 +22,10 @@ What works with NA: * All element-wise ufuncs. * UFunc.reduce methods, with a new skipna parameter. * Array methods: - + ndarray.clip - + ndarray.conjugate, + + ndarray.clip, ndarray.min, ndarray.max, ndarray.sum, ndarray.prod, + + + ndarray.conjugate What doesn't work with NA: * Fancy indexing, such as with lists and partial boolean masks. diff --git a/numpy/core/src/multiarray/calculation.c b/numpy/core/src/multiarray/calculation.c index 9ddbc4b89..b879d0981 100644 --- a/numpy/core/src/multiarray/calculation.c +++ b/numpy/core/src/multiarray/calculation.c @@ -152,7 +152,7 @@ PyArray_ArgMin(PyArrayObject *ap, int axis, PyArrayObject *out) if (PyArray_ISFLEXIBLE(ap)) { PyErr_SetString(PyExc_TypeError, - "argmax is unsupported for this type"); + "argmin is unsupported for this type"); return NULL; } else if (PyArray_ISUNSIGNED(ap)) { diff --git a/numpy/core/src/multiarray/scalarapi.c b/numpy/core/src/multiarray/scalarapi.c index 2b118a5bd..1efee519b 100644 --- a/numpy/core/src/multiarray/scalarapi.c +++ b/numpy/core/src/multiarray/scalarapi.c @@ -424,7 +424,7 @@ PyArray_DescrFromTypeObject(PyObject *type) /* if it's a builtin type, then use the typenumber */ typenum = _typenum_fromtypeobj(type,1); - if (typenum != PyArray_NOTYPE) { + if (typenum != NPY_NOTYPE) { new = PyArray_DescrFromType(typenum); return new; } @@ -433,24 +433,24 @@ PyArray_DescrFromTypeObject(PyObject *type) if ((type == (PyObject *) &PyNumberArrType_Type) || (type == (PyObject *) &PyInexactArrType_Type) || (type == (PyObject *) &PyFloatingArrType_Type)) { - typenum = PyArray_DOUBLE; + typenum = NPY_DOUBLE; } else if (type == (PyObject *)&PyComplexFloatingArrType_Type) { - typenum = PyArray_CDOUBLE; + typenum = NPY_CDOUBLE; } else if ((type == (PyObject *)&PyIntegerArrType_Type) || (type == (PyObject *)&PySignedIntegerArrType_Type)) { - typenum = PyArray_LONG; + typenum = NPY_LONG; } else if (type == (PyObject *) &PyUnsignedIntegerArrType_Type) { - typenum = PyArray_ULONG; + typenum = NPY_ULONG; } else if (type == (PyObject *) &PyCharacterArrType_Type) { - typenum = PyArray_STRING; + typenum = NPY_STRING; } else if ((type == (PyObject *) &PyGenericArrType_Type) || (type == (PyObject *) &PyFlexibleArrType_Type)) { - typenum = PyArray_VOID; + typenum = NPY_VOID; } if (typenum != PyArray_NOTYPE) { @@ -464,7 +464,7 @@ PyArray_DescrFromTypeObject(PyObject *type) /* Do special thing for VOID sub-types */ if (PyType_IsSubtype((PyTypeObject *)type, &PyVoidArrType_Type)) { - new = PyArray_DescrNewFromType(PyArray_VOID); + new = PyArray_DescrNewFromType(NPY_VOID); conv = _arraydescr_fromobj(type); if (conv) { new->fields = conv->fields; diff --git a/numpy/core/src/umath/ufunc_object.c b/numpy/core/src/umath/ufunc_object.c index 8ab632d5b..09360a8d2 100644 --- a/numpy/core/src/umath/ufunc_object.c +++ b/numpy/core/src/umath/ufunc_object.c @@ -2506,7 +2506,7 @@ get_masked_binary_op_function(PyUFuncObject *self, PyArrayObject *arr, NpyAuxData **out_innerloopdata) { int i, retcode; - PyArrayObject *op[3] = {arr, arr, arr}; + PyArrayObject *op[3] = {arr, arr, NULL}; PyArray_Descr *dtype[3] = {NULL, NULL, NULL}; PyObject *type_tup = NULL; @@ -2521,14 +2521,17 @@ get_masked_binary_op_function(PyUFuncObject *self, PyArrayObject *arr, if (otype_dtype == NULL) { return -1; } - type_tup = Py_BuildValue("(N)", otype_dtype); + Py_INCREF(otype_dtype); + Py_INCREF(otype_dtype); + type_tup = Py_BuildValue("(NNN)", + otype_dtype, otype_dtype, otype_dtype); if (type_tup == NULL) { return -1; } } /* Use the type resolution function to find our loop */ - retcode = self->type_resolution_masked_function(self, NPY_SAFE_CASTING, + retcode = self->type_resolution_masked_function(self, NPY_SAME_KIND_CASTING, op, type_tup, dtype, out_innerloop, out_innerloopdata); Py_XDECREF(type_tup); @@ -2991,7 +2994,7 @@ PyUFunc_Reduce(PyUFuncObject *self, PyArrayObject *arr, PyArrayObject *out, PyErr_SetString(PyExc_ValueError, "Cannot assign NA value to an array which " "does not support NAs"); - goto fail; + return NULL; } else { use_maskna = 0; @@ -3032,12 +3035,12 @@ PyUFunc_Reduce(PyUFuncObject *self, PyArrayObject *arr, PyArrayObject *out, } } if (retcode < 0) { - PyArray_Descr *dtype = PyArray_DescrFromType(otype); - PyErr_Format(PyExc_ValueError, - "could not find a matching type for %s.reduce, " - "requested type has type code '%c'", - ufunc_name, dtype ? dtype->type : '-'); - Py_XDECREF(dtype); + //PyArray_Descr *dtype = PyArray_DescrFromType(otype); + //PyErr_Format(PyExc_ValueError, + // "could not find a matching type for %s.reduce, " + // "requested type has type code '%c'", + // ufunc_name, dtype ? dtype->type : '-'); + //Py_XDECREF(dtype); return NULL; } diff --git a/numpy/core/tests/test_maskna.py b/numpy/core/tests/test_maskna.py index cd0830ad7..4a04123e7 100644 --- a/numpy/core/tests/test_maskna.py +++ b/numpy/core/tests/test_maskna.py @@ -735,8 +735,8 @@ def test_array_maskna_clip_method(): assert_equal(np.isna(res), [0,1,0,0,1,0]) assert_equal(res[~np.isna(res)], [4, 7, 4, 7]) -def test_array_maskna_max_min_methods(): - # ndarray.max, ndarray.min +def test_array_maskna_max_min_ptp_methods(): + # ndarray.max, ndarray.min, ndarray.ptp a = np.array([[2, np.NA, 10], [4, 8, 7], [12, 4, np.NA]], maskna=True) @@ -757,6 +757,58 @@ def test_array_maskna_max_min_methods(): assert_equal(np.isna(res), [1,0,1]) assert_equal(res[~np.isna(res)], [4]) + res = a.ptp(axis=0) + assert_equal(np.isna(res), [0,1,1]) + assert_equal(res[~np.isna(res)], [10]) + + res = a.ptp(axis=-1) + assert_equal(np.isna(res), [1,0,1]) + assert_equal(res[~np.isna(res)], [4]) + +def test_array_maskna_sum_prod_methods(): + # ndarray.sum, ndarray.prod + a = np.array([[2, np.NA, 10], + [4, 8, 7], + [12, 4, np.NA]], maskna=True) + + res = a.sum(axis=0) + assert_equal(np.isna(res), [0,1,1]) + assert_equal(res[~np.isna(res)], [18]) + + res = a.sum(axis=-1) + assert_equal(np.isna(res), [1,0,1]) + assert_equal(res[~np.isna(res)], [19]) + + res = a.prod(axis=0) + assert_equal(np.isna(res), [0,1,1]) + assert_equal(res[~np.isna(res)], [2*4*12]) + + res = a.prod(axis=-1) + assert_equal(np.isna(res), [1,0,1]) + assert_equal(res[~np.isna(res)], [4*8*7]) + +def test_array_maskna_std_mean_methods(): + # ndarray.std, ndarray.mean + a = np.array([[2, np.NA, 10], + [4, 8, 7], + [12, 4, np.NA]], maskna=True) + + res = a.mean(axis=0) + assert_equal(np.isna(res), [0,1,1]) + assert_equal(res[~np.isna(res)], [np.array([2,4,12]).mean()]) + + res = a.mean(axis=-1) + assert_equal(np.isna(res), [1,0,1]) + assert_equal(res[~np.isna(res)], [np.array([4,8,7]).mean()]) + + res = a.std(axis=0) + assert_equal(np.isna(res), [0,1,1]) + assert_equal(res[~np.isna(res)], [np.array([2,4,12]).std()]) + + res = a.std(axis=-1) + assert_equal(np.isna(res), [1,0,1]) + assert_equal(res[~np.isna(res)], [np.array([4,8,7]).std()]) + def test_array_maskna_conjugate_method(): # ndarray.conjugate a = np.array([1j, 2+4j, np.NA, 2-1.5j, np.NA], maskna=True) |