Muszę napisać funkcję, która będzie wykrywać, czy dane wejściowe zawierają co najmniej jedną wartość nienumeryczną. Jeśli zostanie znaleziona wartość nieliczbowa, zgłoszę błąd (ponieważ obliczenia powinny zwracać tylko wartość liczbową). Liczba wymiarów tablicy wejściowej nie jest z góry znana - funkcja powinna podawać poprawną wartość niezależnie od ndim. Dodatkową komplikacją może być pojedyncza liczba zmiennoprzecinkowa numpy.float64
lub nawet coś dziwnego, jak tablica zerowymiarowa.
Oczywistym sposobem rozwiązania tego problemu jest napisanie funkcji rekurencyjnej, która wykonuje iterację po każdym iterowalnym obiekcie w tablicy, dopóki nie znajdzie elementu, który nie jest iterabem. Zastosuje numpy.isnan()
funkcję do każdego obiektu, którego nie można iterować. Jeśli zostanie znaleziona co najmniej jedna wartość nieliczbowa, funkcja natychmiast zwróci False. W przeciwnym razie, jeśli wszystkie wartości w iterowalnej są liczbowe, ostatecznie zwróci True.
Działa to dobrze, ale jest dość powolne i spodziewam się, że NumPy ma o wiele lepszy sposób na zrobienie tego. Jaka jest alternatywa, która jest szybsza i bardziej otępiała?
Oto moja makieta:
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
wygląda podejrzanie: „Zwraca fałsz, jeśli istnieje co najmniej jedna wartość nieliczbowa”. Spodziewałbymcontains_nan
się powrotu,True
jeśli tablica zawiera NaN.array(['None', 'None'], dtype=object)
? Czy takie wejście powinno powodować tylko wyjątek?float('nan') in x
. To nie działa.Odpowiedzi:
Powinno to być szybsze niż iterowanie i będzie działać niezależnie od kształtu.
Edycja: 30x szybciej:
Wyniki:
Bonus: działa dobrze dla typów NumPy nie będących tablicami:
źródło
float('nan') in x
nie działa? Wypróbowałem to i python wracaFalse
gdziex = [1,2,3,float('nan')]
.numpy.any
genexp po prostu zwraca genexp; w rzeczywistości nie wykonujesz obliczeń, o których myślisz, że jesteś. Nigdy nie wzywajnumpy.any
Genexp.np.isfinite
zamiastnp.isnan
wykrywania przepełnień liczbowych, niestabilności itp.Jeśli nieskończoność jest możliwą wartością, użyłbym numpy.isfinite
Jeśli wynikiem powyższego jest
True
, tomyarray
nie zawiera wartościnumpy.nan
,numpy.inf
lub-numpy.inf
.numpy.nan
będzie OK znumpy.inf
wartościami, na przykład:źródło
float('nan') in x
nie działa? Wypróbowałem to i python wracaFalse
gdziex = [1,2,3,float('nan')]
.nan
s nie są uważane za równe sobie. Spróbujfloat('nan') == float('nan')
.Pfft! Mikrosekundy! Nigdy nie rozwiązuj problemu w mikrosekundach, który można rozwiązać w nanosekundach.
Zwróć uwagę, że zaakceptowana odpowiedź:
Lepszym rozwiązaniem jest zwrócenie True natychmiast po znalezieniu NAN:
i działa dla n-wymiarów:
Porównaj to z rozwiązaniem numpy natywnym:
Metoda wczesnego wyjścia polega na przyspieszeniu o 3 rzędy lub wielkości (w niektórych przypadkach). Nie jest zbyt odrapany, jak na prostą adnotację.
źródło
Za pomocą numpy 1.3 lub svn możesz to zrobić
Sposób traktowania nans w porównaniach nie był spójny we wcześniejszych wersjach.
źródło
float('nan') in x
nie działa? Wypróbowałem to i python wracaFalse
gdziex = [1,2,3,float('nan')]
.float("nan")==float("nan")
daćFalse
(choć jest to wykonalne, powinno prawdopodobnie zwrócić NAN lub None). Podobnie dziwność z NAN i boolen NULL jest prawdą w wielu językach, w tym w SQL (gdzie NULL = NULL nigdy nie jest prawdą).(np.where(np.isnan(A)))[0].shape[0]
będzie większa niż0
gdybyA
zawierała co najmniej jeden elementnan
,A
może byćn x m
macierzą.Przykład:
źródło