Pergunta

Existe uma função existente no Numpy que me dirá se um valor é um tipo numérico ou uma matriz numpy? Estou escrevendo algum código de processamento de dados que precisa lidar com números em várias representações diferentes (por "número", quero dizer qualquer representação de uma quantidade numérica que possa ser manipulada usando os operadores aritméticos padrão, +, -, *, /, * *).

Alguns exemplos do comportamento que estou procurando

>>> 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

Se não existe essa função, eu sei que não deveria ser difícil escrever um, algo como

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

Mas existem outros tipos numéricos que devo incluir na lista?

Foi útil?

Solução

Como outros responderam, pode haver outros tipos numéricos além dos que você mencionar. Uma abordagem seria verificar explicitamente os recursos que você deseja, com 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)

Isso funciona para todos os seus exemplos, exceto o último, numpy.array(['1']). Isso é porque numpy.ndarray Possui os métodos especiais para operações numéricas, mas aumenta o TypeError se você tentar usá -los de forma inadequada com matrizes de string ou objeto. Você pode adicionar uma verificação explícita para isso como

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

Isso pode ser bom o suficiente.

Mas ... você nunca pode ser 100% Claro que alguém não definirá outro tipo com o mesmo comportamento, então uma maneira mais infalível é realmente tentar fazer um cálculo e pegar a exceção, algo 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

Mas, dependendo da frequência com que você planeja chamar usá -lo e com que argumentos, isso pode não ser prático (pode ser potencialmente lento, por exemplo, com grandes matrizes).

Outras dicas

Em geral, a maneira flexível, rápida e pitônica de lidar com tipos desconhecidos é apenas executar alguma operação neles e obter uma exceção nos tipos inválidos.

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

Parece-me que essa abordagem é mais fácil do que criar alguma função para determinar a certeza absoluta do tipo.

Além disso, Numpy tem numpy.isreal e outras funções semelhantes (numpy.is + Guia deve listá -los).

Todos eles têm seus casos divertidos de canto, mas um deles pode ser útil.

Sua is_numeric é mal definido. Veja meus comentários para sua pergunta.

Outros tipos numéricos podem ser: long, complex, fractions.Fraction, numpy.bool_, numpy.ubyte, ...

operator.isNumberType() retorna True para números python e numpy.array.

Como Python 2.6 você pode usar isinstance(d, numbers.Number) em vez de depreciado operator.isNumberType().

Geralmente, é melhor verificar os recursos do objeto (por exemplo, se você pode adicionar um número inteiro) e não seu tipo.

isinstance(numpy.int32(4), numbers.Number) retorna False, então isso não funciona bem. operator.isNumberType() funciona em todas as variantes de números numpy, no entanto, incluindo numpy.array([1]).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top