Как удалить Нан из списка 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''
user3001937
источник
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]
Vlmercado
источник
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

использовать numpy fancy indexing :

In [29]: countries=np.asarray(countries)

In [30]: countries[countries!='nan']
Out[30]: 
array(['USA', 'UK', 'France'], 
      dtype='|S6')
Zhangxaochen
источник
5

если вы проверите тип элемента

type(countries[1])

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

[i for i in countries if type(i) is not float]
Бейран11
источник
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)
воробей
источник