2009-02-01 12 views
13

Czy istnieje funkcja numpy, która powie mi, czy wartość jest typem liczbowym czy tablicą numpy? Piszę kod przetwarzania danych, który musi obsługiwać liczby w kilku różnych reprezentacjach (przez "numer" mam na myśli dowolną reprezentację liczby numerycznej, którą można manipulować przy użyciu standardowych operatorów arytmetycznych, +, -, *, /, * *).Identyfikowanie typów liczbowych i tablicowych w numpy

Niektóre przykłady zachowanie szukam

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

Jeżeli nie istnieje taka funkcja, wiem, że to nie powinno być trudne, aby napisać, coś

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

ale są są inne typy liczbowe, które powinienem umieścić na liście?

+0

Co powinno zwrócić 'is_numeric ([1,2,3])' i 'is_numeric ([1, '2', 3])'? – jfs

+0

Fałsz w obu przypadkach. Zmienię to na pytanie. –

+0

Co z 'numpy.array ([numpy.array ([1]), numpy.array ([2])])'? – jfs

Odpowiedz

18

Jak inni odpowiedzieli, oprócz tych, o których wspomniałeś, mogą być inne typy liczbowe. Jedno podejście byłoby sprawdzić wyraźnie do możliwości chcesz, coś jak

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

To działa dla wszystkich przykładów, z wyjątkiem ostatniego, numpy.array(['1']). To dlatego, że numpy.ndarray ma specjalne metody dla operacji numerycznych, ale podnosi TypeError, jeśli spróbujesz ich użyć niewłaściwie z tablicami znaków lub obiektów. Możesz dodać wyraźne zaznaczenie tego, tak jak

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

To może być wystarczająco dobre.

Ale ... nigdy nie możesz być 100% pewien, że ktoś nie zdefiniuje innego typu z tym samym zachowaniem, więc bardziej niezawodny sposób jest faktycznie spróbować wykonać obliczenia i uchwycić wyjątek, coś jak

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 

ale w zależności od tego, jak często zamierzasz nazwać go używać i jakie argumenty, to nie może być praktyczny (może to być potencjalnie powolny, np z dużymi tablicami).

+0

'Prawdziwe, fałszywe i numpy tablice z nich wyglądają jak liczby przez te testy, więc musiałyby być zawarte w klauzuli" i nie "; zakładając, że nie chcesz robić na nich matematyki. – Dave

0

Twoja is_numeric jest źle zdefiniowana. Zobacz moje komentarze do twojego pytania.

Inne typy numeryczne mogą być: long, complex, fractions.Fraction, numpy.bool_, numpy.ubyte ...

operator.isNumberType() powraca True liczb Python i numpy.array.

Od wersji Python 2.6 można używać isinstance(d, numbers.Number) zamiast wycofanego operator.isNumberType().

Ogólnie lepiej jest sprawdzić możliwości obiektu (np. Czy można do niego dodać liczbę całkowitą), a nie jego typ.

+0

Tak, ale gdybym miał na myśli dokładną definicję, mógłbym napisać tę funkcję ;-) Zmontowałem więcej informacji. –

5

Ogólnie rzecz biorąc, elastyczny, szybki i pythonic sposób obsługi nieznanych typów jest po prostu wykonać niektóre operacje na nich i wychwycić wyjątek na nieprawidłowe typy.

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

Wydaje mi się, że takie podejście jest łatwiejsze niż zastosowanie specjalnej funkcji do określenia bezwzględnej pewności typu.

+1

To nie jest odpowiedź na to pytanie, ale całkowicie się zgadzam. – jfs

+1

Problem polega na tym, że "5" * 5 działa. – jfs

+0

@JF, to prawda, ale nadal lubię tę odpowiedź na to pytanie. Myślę, że str * int bug będzie łatwiejszy do przechwycenia niż funkcja is_numeric będzie pisać. Weź również pod uwagę, że IIRC, żadna inna operacja matematyczna nie jest zdefiniowana, gdy dwa operandy są typu int i int. – Triptych

0

isinstance(numpy.int32(4), numbers.Number) zwraca False, więc to nie działa. operator.isNumberType() działa na wszystkie warianty numpy liczb, jednak w tym numpy.array([1]).

3

Również numpy ma numpy.isreal i inne podobne funkcje (numpy.is + Tab powinna je wyświetlić).

Wszystkie mają swoje fajne etui na rogu, ale jedna z nich może być przydatna.

+0

'np.isreal (np.array (['bar', 'baz'], dtype = 'O'))' zwraca 'tablicę ([True, True], dtype = bool)'. Te dtype = 'O są typowe z kolumn tekstu pandy, dla isntance. – naught101

+0

Również 'np.isreal (np.nan)' zwraca true. Powinien prawdopodobnie zostać zmieniony na 'isnoncomplex' ... – naught101

Powiązane problemy