Quero descobrir como remover os valores nan da minha matriz. Minha matriz se parece com isso:
x = [1400, 1500, 1600, nan, nan, nan ,1700] #Not in this exact configuration
Como posso remover os nan
valores x
?
Quero descobrir como remover os valores nan da minha matriz. Minha matriz se parece com isso:
x = [1400, 1500, 1600, nan, nan, nan ,1700] #Not in this exact configuration
Como posso remover os nan
valores x
?
Respostas:
Se você estiver usando numpy para suas matrizes, também poderá usar
x = x[numpy.logical_not(numpy.isnan(x))]
Equivalentemente
x = x[~numpy.isnan(x)]
[Obrigado a chbrown pela abreviação adicionada]
Explicação
A função interna numpy.isnan
retorna um array booleano / lógico que tem o valor em True
qualquer lugar que x
não seja um número. Como queremos o oposto, usamos o operador lógico-não, ~
para obter uma matriz com True
s em todo lugar que x
seja um número válido.
Por fim, usamos esse array lógico para indexar no array original x
, para recuperar apenas os valores não-NaN.
x = x[numpy.isfinite(x)]
x = x[~numpy.isnan(x)]
, que é equivalente à resposta original de mutzmatron, mas mais curta. Caso você queira manter seus infinitos por perto, saiba disso numpy.isfinite(numpy.inf) == False
, é claro, mas ~numpy.isnan(numpy.inf) == True
.
np.where(np.isfinite(x), x, 0)
x
não é uma matriz numpy. Se você quiser usar a indexação lógico, ele deve ser um array - por exemplox = np.array(x)
filter(lambda v: v==v, x)
funciona tanto para listas quanto para array numpy, pois v! = v apenas para NaN
x
ser especificado apenas uma vez, em vez de soluções do tipo x[~numpy.isnan(x)]
. Isso é conveniente quando x
é definido por uma expressão longa e você não deseja desorganizar o código criando uma variável temporária para armazenar o resultado dessa expressão longa.
Tente o seguinte:
import math
print [value for value in x if not math.isnan(value)]
Para mais informações, leia em Compreensões de lista .
print ([value for value in x if not math.isnan(value)])
np
pacote: Portanto, retorna sua lista sem os nans:[value for value in x if not np.isnan(value)]
Para mim, a resposta de @jmetz não funcionou, no entanto, usar pandas isnull () funcionou.
x = x[~pd.isnull(x)]
Fazendo o acima:
x = x[~numpy.isnan(x)]
ou
x = x[numpy.logical_not(numpy.isnan(x))]
Eu descobri que a redefinição para a mesma variável (x) não removeu os valores reais de nan e precisava usar uma variável diferente. Configurá-lo para uma variável diferente removeu os nans. por exemplo
y = x[~numpy.isnan(x)]
x
sobrescrever o novo valor (ou seja, sem os NaNs ...) . Você pode fornecer mais informações sobre por que isso pode estar acontecendo?
Como mostrado por outros
x[~numpy.isnan(x)]
trabalho. Mas emitirá um erro se o numpy dtype não for um tipo de dados nativo, por exemplo, se for um objeto. Nesse caso, você pode usar pandas.
x[~pandas.isna(x)] or x[~pandas.isnull(x)]
A resposta aceita muda de forma para matrizes 2D. Apresento uma solução aqui, usando a funcionalidade Pandas dropna () . Funciona para matrizes 1D e 2D. No caso 2D, você pode escolher o clima para descartar a linha ou coluna que contém np.nan
.
import pandas as pd
import numpy as np
def dropna(arr, *args, **kwarg):
assert isinstance(arr, np.ndarray)
dropped=pd.DataFrame(arr).dropna(*args, **kwarg).values
if arr.ndim==1:
dropped=dropped.flatten()
return dropped
x = np.array([1400, 1500, 1600, np.nan, np.nan, np.nan ,1700])
y = np.array([[1400, 1500, 1600], [np.nan, 0, np.nan] ,[1700,1800,np.nan]] )
print('='*20+' 1D Case: ' +'='*20+'\nInput:\n',x,sep='')
print('\ndropna:\n',dropna(x),sep='')
print('\n\n'+'='*20+' 2D Case: ' +'='*20+'\nInput:\n',y,sep='')
print('\ndropna (rows):\n',dropna(y),sep='')
print('\ndropna (columns):\n',dropna(y,axis=1),sep='')
print('\n\n'+'='*20+' x[np.logical_not(np.isnan(x))] for 2D: ' +'='*20+'\nInput:\n',y,sep='')
print('\ndropna:\n',x[np.logical_not(np.isnan(x))],sep='')
Resultado:
==================== 1D Case: ====================
Input:
[1400. 1500. 1600. nan nan nan 1700.]
dropna:
[1400. 1500. 1600. 1700.]
==================== 2D Case: ====================
Input:
[[1400. 1500. 1600.]
[ nan 0. nan]
[1700. 1800. nan]]
dropna (rows):
[[1400. 1500. 1600.]]
dropna (columns):
[[1500.]
[ 0.]
[1800.]]
==================== x[np.logical_not(np.isnan(x))] for 2D: ====================
Input:
[[1400. 1500. 1600.]
[ nan 0. nan]
[1700. 1800. nan]]
dropna:
[1400. 1500. 1600. 1700.]
Uma maneira mais simples é:
numpy.nan_to_num(x)
Documentação: https://docs.scipy.org/doc/numpy/reference/generated/numpy.nan_to_num.html
NaN
s por um número grande, enquanto o OP solicitou a remoção completa dos elementos.
Esta é minha abordagem para filtrar o ndarray "X" para NaNs e infs,
Eu crio um mapa de linhas sem nenhuma NaN
e inf
como a seguir:
idx = np.where((np.isnan(X)==False) & (np.isinf(X)==False))
idx é uma tupla. Sua segunda coluna ( idx[1]
) contém os índices da matriz, onde nenhum NaN nem inf foram encontrados na linha.
Então:
filtered_X = X[idx[1]]
filtered_X
contém X sem NaN
nem inf
.
A resposta de @ jmetz é provavelmente a que a maioria das pessoas precisa; no entanto, gera uma matriz unidimensional, por exemplo, tornando inutilizável remover linhas ou colunas inteiras em matrizes.
Para fazer isso, é necessário reduzir a matriz lógica para uma dimensão e indexar a matriz de destino. Por exemplo, o seguinte removerá as linhas que possuem pelo menos um valor NaN:
x = x[~numpy.isnan(x).any(axis=1)]
Veja mais detalhes aqui .