Як я можу вилучити Nan зі списку Python / NumPy


89

У мене є список, який містить значення, одне із значень, яке я отримав, - 'nan'

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

Я намагався його видалити, але щоразу отримую повідомлення про помилку

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

Коли я спробував це:

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
Це виглядає як рядок "nan", а не фактичне значення NaN.
BrenBarn

1
так, це рядок. [x для x у країнах, якщо x! = 'nan']
MarshalSHI

4
if condition == Trueє непотрібним, ви завжди можете просто зробити if condition.
reem

Жодне із запропонованих рішень не задовольняє. У мене така сама проблема. В основному, це не працює для рядків. Тому у вашому випадку np.isnan('USA')надішле те саме повідомлення про помилку. Якщо я знайду якесь рішення, я завантажу його.
Йохан Обадія,

Відповіді:


127

Питання змінилося, тому відповідь має:

Рядки не можна перевірити за допомогою, math.isnanоскільки це передбачає аргумент float. У вашому countriesсписку у вас є поплавці та рядки.

У вашому випадку має бути достатньо наступного:

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

Стара відповідь

У вашому countriesсписку літералом 'nan'є рядок, а не плаваюча програма Python, nanщо еквівалентно:

float('NaN')

У вашому випадку має бути достатньо наступного:

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

1
Логічно, що ви говорите, це правда. Але у мене не вийшло.
user3001937

Тоді проблема в іншій області, масив, який ви дали, - це рядки, які math.isnan, природно, будуть через помилки.

Так ! коли я друкую вихідні дані, я отримав таке: [nan, 'USA', 'UK', 'France']
user3001937

1
@ user3001937 Я оновив відповідь на основі нової інформації

2
zhangxaochen: це не струна, це поплавок. Уважно подивіться на оновлену відповідь; Lego Stormtroopr перетворює xна рядок, щоб ви могли його порівняти. nanзавжди повертає false для ==, навіть якщо порівнювати з nan, тому це найпростіший спосіб порівняти це.
Безкоштовно Моніка Челліо

17

Проблема полягає в тому, що np.isnan()неправильно обробляються значення рядків. Наприклад, якщо ви це зробите:

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

Однак версія pand pd.isnull()працює для числових і рядкових значень:

pd.isnull("A")
> False

pd.isnull(3)
> False

pd.isnull(np.nan)
> True

pd.isnull(None)
> True

14

На вашому прикладі де ...

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

Оскільки nan не дорівнює nan (nan! = Nan), а країни [0] = nan, слід дотримуватися наступного:

countries[0] == countries[0]
False

Однак

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

Отже, має працювати наступне:

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

1
Це єдина відповідь, яка працює, коли у вас є float ('nan') у списку рядків
kmundnic

13
import numpy as np

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

Це повинно видалити весь NaN. Звичайно, я припускаю, що тут йдеться не про рядок, а про фактичний NaN ( np.nan).


1
Це дає мені помилку: TypeError: ufunc «IsNaN" не підтримується для типів введення, а входи не можуть бути безпечно примушують до будь-якої з підтримуваних типів в відповідно до правила лиття «» безпечний «»
Zak Keirn

1
Чому не просто x[~ np.isnan(x)]:? У numpy не потрібно розуміння списку. Звичайно, я припускаю, що x є масивом numpy.
БСП

Я припустив, що x не буде масивом numpy, як пропонувалось питання.
Аджай Шах,

Це буде очікувати плавання. Не працюватиме зі списками зі рядками @ZakKeirn
Shirish Bajpai


5

якщо ви перевіряєте тип елемента

type(countries[1])

результат буде <class float> таким, що ви зможете використовувати наступний код:

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

4

Мені подобається видаляти відсутні значення з такого списку:

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

1

У вашому прикладі 'nan'є рядок, тому замість використання isnan()просто перевірте рядок

подобається це:

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

0

Інший спосіб зробити це включатиме використання такого фільтру :

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

-1

Я помітив, що Pandas, наприклад, поверне 'nan' для порожніх значень. Оскільки це не рядок, вам потрібно перетворити його в один, щоб відповідати йому. Наприклад:

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)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.