Jak mogę usunąć Nan z listy Python / NumPy


89

Mam listę zawierającą wartości, jedna z wartości, które otrzymałem, to „nan”

countries= [nan, 'USA', 'UK', 'France']

Próbowałem go usunąć, ale za każdym razem pojawia się błąd

cleanedList = [x for x in countries if (math.isnan(x) == True)]
TypeError: a float is required

Kiedy próbowałem tego:

cleanedList = cities[np.logical_not(np.isnan(countries))]
cleanedList = cities[~np.isnan(countries)]

TypeError: ufunc 'isnan' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''

4
To wygląda jak łańcuch "nan", a nie rzeczywista wartość NaN.
BrenBarn,

1
tak, to jest ciąg. [x dla x w krajach, jeśli x! = 'nan']
MarshalSHI,

4
if condition == Truejest niepotrzebne, zawsze możesz to zrobić if condition.
przypomnij sobie

Żadne z dotychczasowych rozwiązań nie jest satysfakcjonujące. Mam ten sam problem. Zasadniczo nie działa w przypadku ciągów. Dlatego w twoim przypadku np.isnan('USA')wyśle ​​ten sam komunikat o błędzie. Jeśli znajdę jakieś rozwiązanie, wrzucę je.
Yohan Obadia

Odpowiedzi:


127

Pytanie się zmieniło, więc odpowiedź:

Ciągów nie można testować przy użyciu, math.isnanponieważ wymaga to argumentu zmiennoprzecinkowego. Na swojej countriesliście masz liczby zmiennoprzecinkowe i łańcuchy.

W Twoim przypadku powinny wystarczyć:

cleanedList = [x for x in countries if str(x) != 'nan']

Stara odpowiedź

Na twojej countriesliście literał 'nan'to łańcuch, a nie liczba zmiennoprzecinkowa w Pythonie, nanktóra jest równoważna z:

float('NaN')

W Twoim przypadku powinny wystarczyć:

cleanedList = [x for x in countries if x != 'nan']

1
Logicznie rzecz biorąc, to, co mówisz, jest prawdą. Ale ze mną nie wyszło.
user3001937

Wtedy problem tkwi w innym obszarze, tablica, którą podałeś, to ciągi znaków, które math.isnannaturalnie przejdą przez błędy.

Tak ! kiedy
drukuję

1
@ user3001937 Zaktualizowałem odpowiedź na podstawie nowych informacji

2
zhangxaochen: to nie jest sznur, to pływak. Przyjrzyj się uważnie zaktualizowanej odpowiedzi; Lego Stormtroopr jest konwertowane xna ciąg, więc możesz to porównać. nanzawsze zwraca wartość false dla ==, nawet w porównaniu z nan, więc jest to najłatwiejszy sposób porównania.
Bezpłatna Monica Cellio

17

Problem wynika z tego, że np.isnan()nie obsługuje poprawnie wartości łańcuchowych. Na przykład, jeśli:

np.isnan("A")
TypeError: ufunc 'isnan' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''

Jednak wersja pandy pd.isnull()działa dla wartości liczbowych i ciągów:

pd.isnull("A")
> False

pd.isnull(3)
> False

pd.isnull(np.nan)
> True

pd.isnull(None)
> True

14

Na przykładzie, w którym ...

countries= [nan, 'USA', 'UK', 'France']

Ponieważ nan nie jest równe nan (nan! = Nan), a kraje [0] = nan, należy przestrzegać następujących zasad:

countries[0] == countries[0]
False

Jednak,

countries[1] == countries[1]
True
countries[2] == countries[2]
True
countries[3] == countries[3]
True

Dlatego powinno działać:

cleanedList = [x for x in countries if x == x]

1
To jedyna odpowiedź, która działa, gdy na liście ciągów znajduje się liczba zmiennoprzecinkowa („nan”)
kmundnic

13
import numpy as np

mylist = [3, 4, 5, np.nan]
l = [x for x in mylist if ~np.isnan(x)]

Powinno to usunąć wszystkie NaN. Oczywiście zakładam, że nie jest to tutaj ciąg znaków, ale rzeczywisty NaN ( np.nan).


1
To daje mi błąd: TypeError: ufunc 'isnan' nie jest obsługiwany dla typów danych wejściowych, a wejścia nie mogły być bezpiecznie przekształcone do żadnego obsługiwanego typu zgodnie z regułą rzutowania
``

1
Dlaczego nie po prostu x[~ np.isnan(x)]:? W numpy nie jest potrzebne rozumienie listy. Oczywiście zakładam, że x jest tablicą numpy.
bue

Założyłem, że x nie będzie tablicą numpy, jak sugerowało pytanie.
Ajay Shah

Oczekuje unoszenia się. Nie będzie działać na listach z ciągami znaków @ZakKeirn
Shirish Bajpai


5

jeśli sprawdzisz typ elementu

type(countries[1])

wynik będzie <class float> taki, że możesz użyć następującego kodu:

[i for i in countries if type(i) is not float]

4

Lubię usuwać brakujące wartości z takiej listy:

list_no_nan = [x for x in list_with_nan if pd.notnull(x)]

1

W twoim przykładzie 'nan'jest to ciąg, więc zamiast używać isnan()po prostu sprawdź ciąg

lubię to:

cleanedList = [x for x in countries if x != 'nan']

0

Innym sposobem na zrobienie tego byłoby użycie takiego filtra :

countries = list(filter(lambda x: str(x) != 'nan', countries))

-1

Zauważyłem, że na przykład Pandy zwracają „nan” dla pustych wartości. Ponieważ nie jest to ciąg, musisz go przekonwertować na jeden, aby go dopasować. Na przykład:

ulist = df.column1.unique() #create a list from a column with Pandas which 
for loc in ulist:
    loc = str(loc)   #here 'nan' is converted to a string to compare with if
    if loc != 'nan':
        print(loc)
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.