Comportamiento extraño de numpy.all con dtypes de objeto

Dada una matriz de dtype=object , numpy.all/any devuelve el último objeto. Por ejemplo:

 >>> from string import ascii_lowercase >>> x = np.array(list(ascii_lowercase), dtype=object) >>> x.all() 'z' 

Al investigar este problema, no pude encontrar mucho a excepción de esta publicación SO aparentemente no relacionada que me llevó a descubrir que se trata de un error abierto en el número (a partir de marzo de 2015): primer informe y problema más relevante . Publicar esto para que otros que lidien con esto puedan encontrar esta información de manera más eficiente.

En la versión numpy 1.8.2 , np.any y np.all comportan como funciones lógicas y / o de corto circuito clásicas. LISP behavor viene a la mente. Python’s and / or operadores hacen esto.

Algunos ejemplos:

 In [203]: np.all(np.array([[1,2],1,[],[1,2,3]],dtype=object)) Out[203]: [] In [204]: np.any(np.array([[1,2],1,[],[1,2,3]],dtype=object)) Out[204]: [1, 2] In [205]: np.any(np.array([0,[],[1,2],1,[],[1,2,3]],dtype=object)) Out[205]: [1, 2] In [206]: np.all(np.array([True,False,[1,2],1,[],[1,2,3]],dtype=object)) Out[206]: False 

np.all devuelve el primer elemento que es lógicamente Falso; de lo contrario el último artículo. np.any el primer elemento que es lógicamente verdadero; de lo contrario el último artículo.

En el mundo LISP, esto se considera una característica útil. No solo deja de evaluar elementos tan pronto como el resultado es claro, sino que también se puede usar la identidad de ese valor de retorno.

¿Hay alguna forma de replicar este comportamiento utilizando los operadores y and/or operadores y algún tipo de mapa o reducción?

 In [8]: 0 or [] or [1,2] or 1 or [1,2,3] Out[8]: [1, 2] ???([0,[],[1,2],1,[1,2,3]]) 

como se sugiere en el comentario:

 In [26]: reduce(lambda a,b:a and b, np.array([1,2,3,[1,2,3]],dtype=object)) Out[26]: [1, 2, 3] 

Esto podría no cortocircuitar todo el bucle. Más bien, cortocircuita cada paso y propaga ese valor hacia adelante. Al usar lambda a,b:b and a devuelve el primer elemento de la lista, no el último. Los tiempos podrían usarse para probar si se está repitiendo a través de toda la matriz (o no).


np.all es un ufunc que se define como np.logical_and.reduce .

https://github.com/numpy/numpy/blob/master/numpy/core/_methods.py

 umr_all = um.logical_and.reduce def _all(a, axis=None, dtype=None, out=None, keepdims=False): return umr_all(a, axis, dtype, out, keepdims) 

logical_and para dtype = object está definido en c source

https://github.com/numpy/numpy/blob/master/numpy/core/src/umath/funcs.inc.src

 /* Emulates Python's 'a and b' behavior */ static PyObject * npy_ObjectLogicalAnd(PyObject *i1, PyObject *i2) 

de manera similar para np.any . Las versiones numéricas de dtype se definen en otra parte donde.

Hay un parche que obliga a np.all/any a devolver dtype=bool . Pero llamando directamente a np.logical_all , puede controlarlo usted mismo.

 In [304]: np.logical_or.reduce(np.array([0,[1,2,3],4],dtype=object)) Out[304]: [1, 2, 3] In [305]: np.logical_or.reduce(np.array([0,[1,2,3],4],dtype=object),dtype=bool) Out[305]: True