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

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

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

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]

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 .


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)]

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]


2

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

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

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

-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)
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.