2009-02-01 13 views
13

¿Existe una función existente en numpy que me diga si un valor es un tipo numérico o una matriz numpy? Estoy escribiendo un código de procesamiento de datos que necesita para manejar números en varias representaciones diferentes (por "número" me refiero a cualquier representación de una cantidad numérica que puede ser manipulado utilizando los operadores aritméticos estándar, +, -, *, /, * *).La identificación de los tipos numéricos y matriz en numpy

Algunos ejemplos del comportamiento Estoy buscando

>>> is_numeric(5) 
True 
>>> is_numeric(123.345) 
True 
>>> is_numeric('123.345') 
False 
>>> is_numeric(decimal.Decimal('123.345')) 
True 
>>> is_numeric(True) 
False 
>>> is_numeric([1, 2, 3]) 
False 
>>> is_numeric([1, '2', 3]) 
False 
>>> a = numpy.array([1, 2.3, 4.5, 6.7, 8.9]) 
>>> is_numeric(a) 
True 
>>> is_numeric(a[0]) 
True 
>>> is_numeric(a[1]) 
True 
>>> is_numeric(numpy.array([numpy.array([1]), numpy.array([2])]) 
True 
>>> is_numeric(numpy.array(['1']) 
False 

Si no existe tal función, ya sé que no debería ser difícil de escribir uno, algo así como

isinstance(n, (int, float, decimal.Decimal, numpy.number, numpy.ndarray)) 

pero son Hay otros tipos numéricos que debo incluir en la lista?

+0

¿Qué debería devolver 'is_numeric ([1,2,3])' y 'is_numeric ([1, '2', 3])'? – jfs

+0

Falso en ambos casos. Voy a editar eso en la pregunta. –

+0

¿Qué pasa con 'numpy.array ([numpy.array ([1]), numpy.array ([2])])'? – jfs

Respuesta

18

Como otros han contestado, podría haber otros tipos numéricos, además de los que mencionas. Un enfoque sería para comprobar explícitamente las capacidades que desea, con algo como

# Python 2 
def is_numeric(obj): 
    attrs = ['__add__', '__sub__', '__mul__', '__div__', '__pow__'] 
    return all(hasattr(obj, attr) for attr in attrs) 

# Python 3 
def is_numeric(obj): 
    attrs = ['__add__', '__sub__', '__mul__', '__truediv__', '__pow__'] 
    return all(hasattr(obj, attr) for attr in attrs) 

Esto funciona para todos los ejemplos excepto la última, numpy.array(['1']). Esto se debe a que numpy.ndarray tiene los métodos especiales para operaciones numéricas, pero plantea TypeError si intenta utilizarlos de forma inapropiada con matrices de cadenas o objetos. Puede agregar una verificación explícita para esto como

... and not (isinstance(obj, ndarray) and obj.dtype.kind in 'OSU') 

Esto puede ser suficiente.

Pero ... nunca se puede 100% seguro de que alguien no definirá otro tipo con el mismo comportamiento, por lo que una forma más infalible es intentar hacer un cálculo y detectar la excepción, algo así como

def is_numeric_paranoid(obj): 
    try: 
     obj+obj, obj-obj, obj*obj, obj**obj, obj/obj 
    except ZeroDivisionError: 
     return True 
    except Exception: 
     return False 
    else: 
     return True 

pero dependiendo de la frecuencia con la que va a llamar a usarlo y con qué argumentos, esto puede no ser práctico (que puede ser potencialmente lenta, por ejemplo, con matrices grandes).

+0

Las matrices 'Verdadero, Falso' y numpy de ellos se ven como números por estas pruebas, por lo que tendrían que incluirse en la cláusula 'y no'; asumiendo que no quieres hacer matemática con ellos. – Dave

0

Su is_numeric está mal definido. Vea mis comentarios a su pregunta.

Otros tipos numéricos podrían ser: long, complex, fractions.Fraction, numpy.bool_, numpy.ubyte, ...

operator.isNumberType() vuelve True para los números de Python y numpy.array.

Desde Python 2.6 puede usar isinstance(d, numbers.Number) en lugar de obsoleto operator.isNumberType().

lo general, es mejor para comprobar las capacidades del objeto (por ejemplo, si se puede añadir un número entero a ella) y no su tipo.

+0

Sí, pero si tuviera una definición exacta en mente, podría haber escrito la función ;-) Edité más información. –

5

En general, la forma flexible, rápido y Pythonic para manejar tipos desconocidos es sólo realizar alguna operación en ellos y capturar una excepción en los tipos válidos.

try: 
    a = 5+'5' 
except TypeError: 
    print "Oops" 

Me parece que este enfoque es más fácil que la carcasa especial a cabo alguna función para determinar el tipo de certeza absoluta.

+1

No es una respuesta a la pregunta, pero estoy totalmente de acuerdo. – jfs

+1

El problema es que '5' * 5 funciona. – jfs

+0

@JF, eso es cierto, pero todavía me gusta esta respuesta a esta pregunta. Creo que el error str * int será más fácil de capturar que la función is_numeric será escribir. Además, considere que, IIRC, no se define ninguna otra operación matemática donde los dos operandos son str e int. – Triptych

0

isinstance(numpy.int32(4), numbers.Number) devuelve False, por lo que no funciona. operator.isNumberType() funciona en todas las variantes de números numpy, sin embargo, incluido numpy.array([1]).

3

Además, numpy tiene numpy.isreal y otras funciones similares (numpy.is + Tab debe listarlas).

Todos tienen sus fundas de esquina divertidas, pero una de ellas podría ser útil.

+0

'np.isreal (np.array (['bar', 'baz'], dtype = 'O'))' devuelve 'array ([True, True], dtype = bool)'. Esos dtype = 'O's son comunes de las columnas de texto de pandas, para isntance .. – naught101

+0

Además, 'np.isreal (np.nan)' devuelve verdadero. Debería ser renombrado como 'isnoncomplex' ... – naught101

Cuestiones relacionadas