Usuwanie wartości nan z tablicy

223

Chcę dowiedzieć się, jak usunąć wartości nan z mojej tablicy. Moja tablica wygląda mniej więcej tak:

x = [1400, 1500, 1600, nan, nan, nan ,1700] #Not in this exact configuration

Jak mogę usunąć nanwartości x?

Dax Feliz
źródło
Aby być jasnym, przez „usuń NaN” masz na myśli odfiltrowanie tylko podzbioru wartości niepustych . Nie „wypełniaj NaN pewną wartością (zero, stała, średnia, mediana itp.)”
smci,

Odpowiedzi:

362

Jeśli używasz numpy do swoich tablic, możesz także użyć

x = x[numpy.logical_not(numpy.isnan(x))]

Równoważnie

x = x[~numpy.isnan(x)]

[Podziękowania dla chbrown za dodanie stenografii]

Wyjaśnienie

Funkcja wewnętrzna numpy.isnanzwraca tablicę logiczną / logiczną, która ma wartość Truewszędzie, gdzie xnie jest liczbą. W przeciwieństwie do tego, używamy logicznego operatora, ~aby uzyskać tablicę Truezs wszędzie, gdzie x jest poprawna liczba.

Na koniec używamy tej tablicy logicznej do indeksowania do oryginalnej tablicy x, aby pobrać tylko wartości inne niż NaN.

jmetz
źródło
31
Lubx = x[numpy.isfinite(x)]
leniwy 1
14
Lub x = x[~numpy.isnan(x)], co odpowiada oryginalnej odpowiedzi mutzmatronu, ale jest krótsze. Jeśli chcesz zachować swoje nieskończoności, wiedz o tym numpy.isfinite(numpy.inf) == Falseoczywiście, ale ~numpy.isnan(numpy.inf) == True.
chbrown,
8
Dla osób, które chcą rozwiązać ten problem za pomocą ndarray i zachować wymiary, użyj numpy gdzie :np.where(np.isfinite(x), x, 0)
BoltzmannBrain
1
TypeError: tylko tablice skalarne liczb całkowitych mogą być konwertowane na indeks skalarny
towry
1
@towry: dzieje się tak, ponieważ dane wejściowe xnie są tablicami liczbowymi. Jeśli chcesz użyć indeksowania logicznego, musi to być tablica - np.x = np.array(x)
jmetz
50
filter(lambda v: v==v, x)

działa zarówno dla list, jak i tablicy numpy, ponieważ v! = v tylko dla NaN

udibr
źródło
5
Hack, ale szczególnie przydatny w przypadku, gdy filtrujesz nans z tablicy obiektów o mieszanych typach, takich jak łańcuchy i nans.
Austin Richardson
Bardzo czyste rozwiązanie.
Moondra
2
Może się to wydawać sprytne, ale jeśli zasłania logikę i teoretycznie inne obiekty (takie jak klasy niestandardowe) mogą również mieć tę właściwość
Chris_Rands
Przydatny również, ponieważ należy xgo podać tylko raz, w przeciwieństwie do rozwiązań tego typu x[~numpy.isnan(x)]. Jest to wygodne, gdy xjest zdefiniowane długim wyrażeniem i nie chcesz zaśmiecać kodu, tworząc tymczasową zmienną do przechowywania wyniku tego długiego wyrażenia.
Christian O'Reilly,
34

Spróbuj tego:

import math
print [value for value in x if not math.isnan(value)]

Aby uzyskać więcej informacji, zapoznaj się z listami .

liori
źródło
5
Jeśli używasz numpy, zarówno moja odpowiedź, jak i @ @ lazy1 są prawie o rząd wielkości szybsze niż zrozumienie listy - rozwiązanie lazy1 jest nieco szybsze (choć technicznie nie zwróci również żadnych wartości nieskończoności).
jmetz
Nie zapomnij o nawiasach :)print ([value for value in x if not math.isnan(value)])
odsyła
Jeśli używasz numpy jak najwyższej odpowiedzi, możesz użyć tej odpowiedzi ze zrozumieniem listy w nppakiecie: Więc zwraca listę bez nans:[value for value in x if not np.isnan(value)]
yeliabsalohcin
23

Dla mnie odpowiedź @jmetz nie działała, jednak użycie pandas isnull () działało.

x = x[~pd.isnull(x)]
Daniel Kislyuk
źródło
6

Wykonując powyższe:

x = x[~numpy.isnan(x)]

lub

x = x[numpy.logical_not(numpy.isnan(x))]

Odkryłem, że zresetowanie do tej samej zmiennej (x) nie usunęło rzeczywistych wartości nan i musiałem użyć innej zmiennej. Ustawienie innej zmiennej usunęło nans. na przykład

y = x[~numpy.isnan(x)]
melissaOu
źródło
To jest dziwne; zgodnie z dokumentacją indeksowanie tablic boolowskich (które to jest), podlega zaawansowanemu indeksowaniu, które najwyraźniej „zawsze zwraca kopię danych”, dlatego należy xnadpisywać nową wartością (tj. bez NaNs ...) . Czy możesz podać więcej informacji, dlaczego tak się dzieje?
jmetz
5

Jak pokazują inni

x[~numpy.isnan(x)]

Pracuje. Ale wyrzuci błąd, jeśli typ numpy nie jest rodzimym typem danych, na przykład jeśli jest obiektem. W takim przypadku możesz użyć pand.

x[~pandas.isna(x)] or x[~pandas.isnull(x)]
koliyat9811
źródło
4

Odpowiedź Zaakceptowany zmienia kształt 2D tablic. Przedstawiam tutaj rozwiązanie, wykorzystujące funkcjonalność Panda Dropna () . Działa dla tablic 1D i 2D. W przypadku 2D możesz wybrać pogodę, aby upuścić wiersz lub kolumnę zawierającą np.nan.

import pandas as pd
import numpy as np

def dropna(arr, *args, **kwarg):
    assert isinstance(arr, np.ndarray)
    dropped=pd.DataFrame(arr).dropna(*args, **kwarg).values
    if arr.ndim==1:
        dropped=dropped.flatten()
    return dropped

x = np.array([1400, 1500, 1600, np.nan, np.nan, np.nan ,1700])
y = np.array([[1400, 1500, 1600], [np.nan, 0, np.nan] ,[1700,1800,np.nan]] )


print('='*20+' 1D Case: ' +'='*20+'\nInput:\n',x,sep='')
print('\ndropna:\n',dropna(x),sep='')

print('\n\n'+'='*20+' 2D Case: ' +'='*20+'\nInput:\n',y,sep='')
print('\ndropna (rows):\n',dropna(y),sep='')
print('\ndropna (columns):\n',dropna(y,axis=1),sep='')

print('\n\n'+'='*20+' x[np.logical_not(np.isnan(x))] for 2D: ' +'='*20+'\nInput:\n',y,sep='')
print('\ndropna:\n',x[np.logical_not(np.isnan(x))],sep='')

Wynik:

==================== 1D Case: ====================
Input:
[1400. 1500. 1600.   nan   nan   nan 1700.]

dropna:
[1400. 1500. 1600. 1700.]


==================== 2D Case: ====================
Input:
[[1400. 1500. 1600.]
 [  nan    0.   nan]
 [1700. 1800.   nan]]

dropna (rows):
[[1400. 1500. 1600.]]

dropna (columns):
[[1500.]
 [   0.]
 [1800.]]


==================== x[np.logical_not(np.isnan(x))] for 2D: ====================
Input:
[[1400. 1500. 1600.]
 [  nan    0.   nan]
 [1700. 1800.   nan]]

dropna:
[1400. 1500. 1600. 1700.]
Markus Dutschke
źródło
3

Jeśli używasz numpy

# first get the indices where the values are finite
ii = np.isfinite(x)

# second get the values
x = x[ii]
aloha
źródło
0

To jest moje podejście do filtrowania ndarray „X” dla NaNs i infs,

Utworzyć mapę wierszy bez NaNa każdy inf, co następuje:

idx = np.where((np.isnan(X)==False) & (np.isinf(X)==False))

idx to krotka. Druga kolumna ( idx[1]) zawiera indeksy tablicy, w których nie znaleziono NaN ani inf w poprzek wiersza.

Następnie:

filtered_X = X[idx[1]]

filtered_Xzawiera X bez NaN nor inf.

aerijman
źródło
0

Odpowiedź @ jmetz jest prawdopodobnie najbardziej potrzebna; daje jednak jednowymiarową tablicę, np. uniemożliwia usunięcie całych wierszy lub kolumn w macierzach.

W tym celu należy zredukować tablicę logiczną do jednego wymiaru, a następnie zindeksować tablicę docelową. Na przykład następujące usunie wiersze, które mają co najmniej jedną wartość NaN:

x = x[~numpy.isnan(x).any(axis=1)]

Zobacz więcej szczegółów tutaj .

M4urice
źródło