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