Rimozione di valori nan da un array


223

Voglio capire come rimuovere i valori nan dal mio array. Il mio array è simile al seguente:

x = [1400, 1500, 1600, nan, nan, nan ,1700] #Not in this exact configuration

Come posso rimuovere i nanvalori da x?


Per essere chiari, per "rimuovere NaNs" intendi filtrare solo il sottoinsieme di valori non nulli . Non "riempire le NaN con un certo valore (zero, costante, media, mediana, ecc.)"
smci

Risposte:


362

Se stai usando numpy per le tue matrici, puoi anche usare

x = x[numpy.logical_not(numpy.isnan(x))]

Equivalentemente

x = x[~numpy.isnan(x)]

[Grazie a chbrown per la scorciatoia aggiunta]

Spiegazione

La funzione interna, numpy.isnanrestituisce un array booleano / logico che ha Trueovunque un valore xdiverso da un numero. Come vogliamo il contrario, usiamo l'operatore non logico, ~per ottenere un array con Trues ovunque che x sia un numero valido.

Infine usiamo questo array logico per indicizzare l'array originale x, per recuperare solo i valori non NaN.


31
Oppurex = x[numpy.isfinite(x)]
lazy1,

14
Oppure x = x[~numpy.isnan(x)], che equivale alla risposta originale di mutzmatron, ma più breve. Nel caso in cui desideri mantenere i tuoi infiniti, sappi che numpy.isfinite(numpy.inf) == False, ovviamente, ma ~numpy.isnan(numpy.inf) == True.
Chbrown,

8
Per le persone che cercano di risolvere questo problema con un ndarray e mantenere le dimensioni, usare intorpidito dove :np.where(np.isfinite(x), x, 0)
BoltzmannBrain

1
TypeError: solo gli array scalari interi possono essere convertiti in un indice scalare
towry

1
@towry: questo accade perché il tuo input xnon è un array intorpidito. Se si desidera utilizzare l'indicizzazione logica, deve essere un array - ad esempiox = np.array(x)
jmetz,

50
filter(lambda v: v==v, x)

funziona sia per elenchi che per numpy array poiché v! = v solo per NaN


5
Un hack, ma particolarmente utile nel caso in cui si filtrano nans da una matrice di oggetti con tipi misti, come stringhe e nans.
Austin Richardson,

Soluzione molto pulita.
Moondra,

2
Questo potrebbe sembrare intelligente, ma se oscura la logica e teoricamente anche altri oggetti (come le classi personalizzate) possono avere questa proprietà
Chris_Rands

Utile anche perché deve xessere specificato solo una volta rispetto alle soluzioni del tipo x[~numpy.isnan(x)]. Ciò è utile quando xè definito da un'espressione lunga e non si desidera ingombrare il codice creando una variabile temporanea per memorizzare il risultato di questa espressione lunga.
Christian O'Reilly,

34

Prova questo:

import math
print [value for value in x if not math.isnan(value)]

Per ulteriori informazioni, leggi l' elenco Comprensioni .


5
Se stai usando numpy sia la mia risposta che quella di @ lazy1 sono quasi un ordine di grandezza più veloci della comprensione dell'elenco - la soluzione di lazy1 è leggermente più veloce (anche se tecnicamente non restituirà alcun valore di infinito).
jmetz,

Non dimenticare le parentesi :)print ([value for value in x if not math.isnan(value)])
ipersona il

Se stai usando numpy come la risposta migliore, puoi usare questa risposta di comprensione della lista con il nppacchetto: Quindi restituisce la tua lista senza i nans:[value for value in x if not np.isnan(value)]
yeliabsalohcin

23

Per me la risposta di @jmetz non ha funzionato, tuttavia usando panda isnull () ha funzionato.

x = x[~pd.isnull(x)]

6

Fare quanto sopra:

x = x[~numpy.isnan(x)]

o

x = x[numpy.logical_not(numpy.isnan(x))]

Ho scoperto che il ripristino sulla stessa variabile (x) non ha rimosso i valori nan effettivi e ha dovuto utilizzare una variabile diversa. Impostandolo su una variabile diversa rimosso i nans. per esempio

y = x[~numpy.isnan(x)]

Questo è strano; secondo i documenti , l'indicizzazione booleana dell'array (che è), è sotto indicizzazione avanzata che apparentemente "restituisce sempre una copia dei dati", quindi dovresti xsovrascrivere con il nuovo valore (cioè senza i NaNs ...) . Potete fornire ulteriori informazioni sul perché ciò potrebbe accadere?
jmetz,

5

Come mostrato da altri

x[~numpy.isnan(x)]

lavori. Ma genererà un errore se il tipo numpy non è un tipo di dati nativo, ad esempio se è un oggetto. In quel caso puoi usare i panda.

x[~pandas.isna(x)] or x[~pandas.isnull(x)]

4

La risposta accettata cambia forma per array 2d. Vi presento una soluzione qui, usando la funzionalità di Pandas dropna () . Funziona con array 1D e 2D. Nel caso 2D puoi scegliere il tempo in cui rilasciare la riga o la colonna contenente 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='')

Risultato:

==================== 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.]

3

Se stai usando numpy

# first get the indices where the values are finite
ii = np.isfinite(x)

# second get the values
x = x[ii]


0

Questo è il mio approccio per filtrare ndarray "X" per NaNs e infs,

Creo una mappa di righe senza nessuna NaNe nessuna infcome segue:

idx = np.where((np.isnan(X)==False) & (np.isinf(X)==False))

idx è una tupla. La sua seconda colonna ( idx[1]) contiene gli indici dell'array, dove nessun NaNinf sono stati trovati lungo la riga.

Poi:

filtered_X = X[idx[1]]

filtered_Xcontiene X senza NaN nor inf.


0

La risposta di @jmetz è probabilmente quella di cui molte persone hanno bisogno; tuttavia produce una matrice unidimensionale, ad esempio rendendo inutilizzabile la rimozione di intere righe o colonne nelle matrici.

Per fare ciò, si dovrebbe ridurre l'array logico a una dimensione, quindi indicizzare l'array di destinazione. Ad esempio, quanto segue rimuoverà le righe che hanno almeno un valore NaN:

x = x[~numpy.isnan(x).any(axis=1)]

Vedi maggiori dettagli qui .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.