Como posso remover Nan da lista Python / NumPy

96

Eu tenho uma lista que contém valores, um dos valores que recebi é 'nan'

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

Eu tentei removê-lo, mas sempre recebo um erro

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

Quando eu tentei este:

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
fonte
4
Isso se parece com a string "nan", não com um valor NaN real.
BrenBarn
1
sim, é uma corda. [x para x em países se x! = 'nan']
MarshalSHI
4
if condition == Trueé desnecessário, você sempre pode apenas fazer if condition.
reem
Nenhuma solução fornecida até agora não são satisfatórias. Eu tenho o mesmo problema. Basicamente, não funciona com strings. Portanto no seu caso np.isnan('USA')enviaremos a mesma mensagem de erro. Se eu encontrar alguma solução, irei fazer o upload.
Yohan Obadia

Respostas:

131

A pergunta mudou, então a tem a resposta:

Strings não podem ser testados usando, math.isnanpois isso espera um argumento float. Em sua countrieslista, você tem flutuadores e strings.

No seu caso, o seguinte deve ser suficiente:

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

Resposta antiga

Na tua countries lista, o literal 'nan'é uma string, não o flutuante Python, nanque é equivalente a:

float('NaN')

No seu caso, o seguinte deve ser suficiente:

cleanedList = [x for x in countries if x != 'nan']
Comunidade
fonte
1
Logicamente, o que você diz é verdade. Mas não funcionou comigo.
user3001937
Então o problema está em outra área, o array que você forneceu são strings que math.isnanirão naturalizar através de erros com.
Sim ! quando imprimo a saída,
recebo
1
@ user3001937 Atualizei a resposta com base nas novas informações
2
zhangxaochen: não é uma corda, é um flutuador. Observe atentamente a resposta atualizada; Lego Stormtroopr está sendo convertido xem uma string para que você possa compará-la. nansempre retorna falso para ==, mesmo quando comparado com nan, então essa é a maneira mais fácil de comparar.
Grátis Monica Cellio
17

O problema vem do fato de que np.isnan()não trata os valores das strings corretamente. Por exemplo, se você:

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

No entanto, a versão do pandas pd.isnull()funciona para valores numéricos e de string:

pd.isnull("A")
> False

pd.isnull(3)
> False

pd.isnull(np.nan)
> True

pd.isnull(None)
> True
Yohan Obadia
fonte
15

Usando seu exemplo onde ...

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

Como nan não é igual a nan (nan! = Nan) e países [0] = nan, você deve observar o seguinte:

countries[0] == countries[0]
False

Contudo,

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

Portanto, o seguinte deve funcionar:

cleanedList = [x for x in countries if x == x]
vlmercado
fonte
1
Esta é a única resposta que funciona quando você tem um float ('nan') em uma lista de strings
kmundnic
13
import numpy as np

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

Isso deve remover todo o NaN. Claro, presumo que não seja uma string aqui, mas sim um NaN ( np.nan) real .

Ajay Shah
fonte
1
Isso me dá o erro: TypeError: ufunc 'isnan' não suportado para os tipos de entrada, e as entradas não puderam ser coagidas com segurança para nenhum tipo suportado de acordo com a regra de fundição '' seguro ''
Zak Keirn
1
Por que não simplesmente x[~ np.isnan(x)]:? Nenhuma compreensão de lista necessária em entorpecido. Claro, suponho que x é uma matriz numpy.
bue
Presumi que x não seria uma matriz numpy como a pergunta sugeria.
Ajay Shah
Esperará flutuar. Não funciona em listas com strings @ZakKeirn
Bajpai
7

Eu gosto de remover valores ausentes de uma lista como esta:

list_no_nan = [x for x in list_with_nan if pd.notnull(x)]
Aaron Inglaterra
fonte
6

se você verificar o tipo de elemento

type(countries[1])

o resultado será <class float> para que você possa usar o seguinte código:

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

use indexação fantasia numpy :

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

In [30]: countries[countries!='nan']
Out[30]: 
array(['USA', 'UK', 'France'], 
      dtype='|S6')
Zhangxaochen
fonte
2

Outra maneira de fazer isso incluiria o uso de filtros como este:

countries = list(filter(lambda x: str(x) != 'nan', countries))
Sorin Dragan
fonte
1

No seu exemplo 'nan'está uma string, então, em vez deisnan() apenas verifique a string

como isso:

cleanedList = [x for x in countries if x != 'nan']
Serial
fonte
-1

Percebi que o Pandas, por exemplo, retornará 'nan' para valores em branco. Uma vez que não é uma string, você precisa convertê-la em um para combiná-la. Por exemplo:

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)
pardal
fonte