Как удалить Нан из списка 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 09

1
да, это строка. [x
вместо

4
if condition == Trueне нужно, всегда можно просто сделать if condition.
reem

Ни одно из предложенных на данный момент решений не удовлетворяет. У меня такая же проблема. В принципе, для строк это не работает. Поэтому в вашем случае np.isnan('USA')будет отправлено такое же сообщение об ошибке. Если найду какое-то решение, выложу.
Йохан Обадиа

Ответы:


127

Вопрос изменился, поэтому есть ответ:

Строки не могут быть протестированы с использованием, math.isnanпоскольку ожидается аргумент с плавающей запятой. В вашем 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 09

Тогда проблема в другой области, массив, который вы дали, представляет собой строки, которые math.isnan, естественно, будут содержать ошибки.

Да ! когда я распечатываю результат, я получил следующее: [nan, 'USA', 'UK', 'France']
user3001937

1
@ user3001937 Я обновил ответ на основе новой информации

2
zhangxaochen: это не строка, это поплавок. Внимательно посмотрите обновленный ответ; Конвертация Lego Stormtroopr xв строку, чтобы вы могли ее сравнить. nanвсегда возвращает false для ==, даже если сравнивать с nan, так что это самый простой способ сравнить.
Free Monica Cellio,

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

Однако версия pandas 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), а country [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
Это единственный ответ, который работает, когда у вас есть число с плавающей запятой ('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' не поддерживается для типов ввода, и входные данные не могут быть безопасно приведены к каким-либо поддерживаемым типам в соответствии с правилом приведения «безопасно»
Зак Кейрн,

1
Почему не просто x[~ np.isnan(x)]:? В numpy не требуется понимание списка. Конечно, я предполагаю, что x - массив numpy.
БСП

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

Он будет ожидать float. Не будет работать в списках со строками @ZakKeirn
Shirish Баджпаи


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.