Necesito escribir una función que detecte si la entrada contiene al menos un valor que no sea numérico. Si se encuentra un valor no numérico, generaré un error (porque el cálculo solo debe devolver un valor numérico). El número de dimensiones de la matriz de entrada no se conoce de antemano; la función debe dar el valor correcto independientemente de ndim. Como complicación adicional, la entrada podría ser un solo flotador numpy.float64
o incluso algo extraño como una matriz de dimensión cero.
La forma obvia de resolver esto es escribir una función recursiva que itera sobre cada objeto iterable en la matriz hasta que encuentra un no iterabe. Aplicará la numpy.isnan()
función sobre cada objeto no iterable. Si se encuentra al menos un valor no numérico, la función devolverá False inmediatamente. De lo contrario, si todos los valores del iterable son numéricos, eventualmente devolverá True.
Eso funciona bien, pero es bastante lento y espero que NumPy tenga una forma mucho mejor de hacerlo. ¿Cuál es una alternativa que es más rápida y numpyish?
Aquí está mi maqueta:
def contains_nan( myarray ):
"""
@param myarray : An n-dimensional array or a single float
@type myarray : numpy.ndarray, numpy.array, float
@returns: bool
Returns true if myarray is numeric or only contains numeric values.
Returns false if at least one non-numeric value exists
Not-A-Number is given by the numpy.isnan() function.
"""
return True
contains_nan
parece sospechosa: "Devuelve falso si existe al menos un valor no numérico". Hubiera esperadocontains_nan
regresarTrue
si la matriz contiene NaN.array(['None', 'None'], dtype=object)
? ¿Debería tal entrada generar una excepción?float('nan') in x
. No funciona.Respuestas:
Esto debería ser más rápido que iterar y funcionará independientemente de la forma.
Editar: 30 veces más rápido:
Resultados:
Bono: funciona bien para tipos NumPy que no son de matriz:
fuente
float('nan') in x
no funciona? Lo probé y Python regresaFalse
dondex = [1,2,3,float('nan')]
.numpy.any
a genexp solo devuelve genexp; en realidad no está haciendo el cálculo que cree que está haciendo. Nunca llamenumpy.any
a un genexp.np.isfinite
lugar denp.isnan
detectar desbordamientos numéricos, inestabilidad, etc.Si infinito es un valor posible, usaría numpy.isfinite
Si lo anterior se evalúa como
True
, entoncesmyarray
no contiene valoresnumpy.nan
,numpy.inf
o-numpy.inf
.numpy.nan
estará bien con losnumpy.inf
valores, por ejemplo:fuente
float('nan') in x
no funciona? Lo probé y Python regresaFalse
dondex = [1,2,3,float('nan')]
.nan
s no se consideran iguales entre sí. Pruebafloat('nan') == float('nan')
.¡No! Microsegundos! Nunca resuelva un problema en microsegundos que pueda resolverse en nanosegundos.
Tenga en cuenta que la respuesta aceptada:
Una mejor solución es devolver True inmediatamente cuando se encuentra NAN:
y funciona para n dimensiones:
Compare esto con la solución nativa numpy:
El método de salida anticipada es de 3 órdenes o aceleración de magnitud (en algunos casos). No está mal para una simple anotación.
fuente
Con numpy 1.3 o svn puedes hacer esto
El tratamiento de los nans en las comparaciones no fue consistente en versiones anteriores.
fuente
float('nan') in x
no funciona? Lo probé y Python regresaFalse
dondex = [1,2,3,float('nan')]
.float("nan")==float("nan")
darFalse
(aunque es factible que probablemente debería devolver NAN o None). De manera similar, la rareza con NAN y boolen NULL es cierta en muchos idiomas, incluido SQL (donde NULL = NULL nunca es cierto).(np.where(np.isnan(A)))[0].shape[0]
será mayor que0
siA
contiene al menos un elemento denan
,A
podría ser unan x m
matriz.Ejemplo:
fuente