Pregunta

Hay una función existente en numpy que me va a decir si un valor es de tipo numérico o una colección de matriz?Estoy escribiendo algunos de procesamiento de datos de código que necesita para manejar los números en diferentes representaciones (por "número de" me refiero a cualquier representación de un numérico de la cantidad que se puede manipular con el estándar de los operadores aritméticos, +, -, *, /, **).

Algunos ejemplos de comportamiento que 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 hay tal función existe, sé que no debería ser difícil para escribir uno, algo así como

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

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

¿Fue útil?

Solución

Como han respondido otros, podría haber otros tipos numéricos además de los que mencionas. Un enfoque sería verificar 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 sus ejemplos, excepto el último, numpy.array(['1']). Esto se debe a que numpy.ndarray tiene los métodos especiales para las operaciones numéricas, pero genera TypeError si intenta usarlos de manera inapropiada con cadenas o matrices de 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 lo suficientemente bueno.

Pero ... nunca se puede estar 100% seguro de que alguien no definirá otro tipo con el mismo comportamiento, por lo que una forma más infalible es tratar de hacer un cálculo y capturar el 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 pienses usarlo y con qué argumentos, esto puede no ser práctico (puede ser potencialmente lento, por ejemplo, con matrices grandes).

Otros consejos

En general, la forma flexible, rápida y pitónica de manejar tipos desconocidos es simplemente realizar alguna operación en ellos y detectar una excepción en los tipos no válidos.

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

Me parece que este enfoque es más fácil que el uso especial de algunas funciones para determinar la certeza absoluta de tipo.

También, numpy ha numpy.isreal y otras funciones similares (numpy.is + Ficha debe tener una lista de ellos).

Todos ellos tienen su diversión casos de esquina pero uno de los que podría ser útil.

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

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

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

Desde Python 2.6 puede usar isinstance(d, numbers.Number) en lugar de obsoleto <=>.

Generalmente es mejor verificar las capacidades del objeto (por ejemplo, si puede agregarle un número entero) y no su tipo.

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

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top