Qual è la differenza tra NaN e None?


94

Sto leggendo due colonne di un file csv usando i panda readcsv()e quindi assegnando i valori a un dizionario. Le colonne contengono stringhe di numeri e lettere. Occasionalmente ci sono casi in cui una cella è vuota. A mio parere, il valore letto in quella voce del dizionario dovrebbe essere Nonema invece nanè assegnato. Sicuramente Noneè più descrittivo di una cella vuota in quanto ha un valore nullo, mentre nandice solo che il valore letto non è un numero.

La mia comprensione è corretta, qual è la differenza tra Nonee nan? Perché viene nanassegnato invece di None?

Inoltre, il mio controllo del dizionario per eventuali celle vuote ha utilizzato numpy.isnan():

for k, v in my_dict.iteritems():
    if np.isnan(v):

Ma questo mi dà un errore dicendo che non posso usare questo controllo per v. Immagino sia perché si intende utilizzare un numero intero o una variabile float, non una stringa. Se questo è vero, come posso verificare la presenza vdi una "cella vuota" / nancaso?


Il testo qwertynon è un numero.
Robert Harvey

1
@RobertHarvey lo so, quindi sicuramente Nonesarebbe una descrizione migliore del valore di una cella vuota.
user1083734

Risposte:


107

NaN viene utilizzato come segnaposto per i dati mancanti in modo coerente nei panda , la coerenza è buona. Di solito leggo / traduco NaN come "mancante" . Vedi anche "lavorare con i dati mancanti" nei documenti.

Wes scrive nella documentazione "scelta della rappresentazione di NA" :

Dopo anni di produzione, l'uso di [NaN] si è dimostrato, almeno secondo me, la decisione migliore vista la situazione in NumPy e Python in generale. Il valore speciale NaN (Not-A-Number) viene utilizzato ovunque come valore NA e ci sono funzioni API isnulle notnullche possono essere utilizzate tra i dtypes per rilevare i valori NA.
...
Pertanto, ho scelto l'approccio pitonico "la praticità batte la purezza" e ho scambiato la capacità NA intera per un approccio molto più semplice di utilizzare un valore speciale in float e array di oggetti per denotare NA e promuovere gli array interi a fluttuanti quando i NA devono essere introdotto.

Nota: il "gotcha" che la serie intera contenente dati mancanti viene trasmessa in virgola mobile .

A mio parere, il motivo principale per utilizzare NaN (su None) è che può essere memorizzato con float64 dtype di numpy, piuttosto che con l'oggetto meno efficiente dtype, vedere promozioni di tipo NA .

#  without forcing dtype it changes None to NaN!
s_bad = pd.Series([1, None], dtype=object)
s_good = pd.Series([1, np.nan])

In [13]: s_bad.dtype
Out[13]: dtype('O')

In [14]: s_good.dtype
Out[14]: dtype('float64')

Jeff commenta (sotto) su questo:

np.nanconsente operazioni vettorializzate; è un valore float, mentre None, per definizione, forza il tipo di oggetto, che sostanzialmente disabilita tutta l'efficienza in numpy.

Quindi ripeti 3 volte velocemente: oggetto == cattivo, float == buono

Detto questo, molte operazioni potrebbero ancora funzionare altrettanto bene con None vs NaN (ma forse non sono supportate, ovvero a volte possono dare risultati sorprendenti ):

In [15]: s_bad.sum()
Out[15]: 1

In [16]: s_good.sum()
Out[16]: 1.0

Per rispondere alla seconda domanda:
dovresti usare pd.isnulle pd.notnullper testare i dati mancanti (NaN).


19
semplicemente aggiungendo 2c qui .... np.nanconsente operazioni vettorializzate; è un valore float, mentre Noneper definizione forza il objecttipo, e fondamentalmente disabilita tutta l'efficienza in numpy, quindi ripeti 3 volte velocemente:object==bad, float==good
Jeff

1
È <NA>anche un np.nan?
Gathide

18

NaN può essere usato come valore numerico su operazioni matematiche, mentre None non può (o almeno non dovrebbe).

NaNè un valore numerico, come definito nello standard a virgola mobile IEEE 754 . Noneè un tipo Python interno (NoneType ) e sarebbe più come "inesistente" o "vuoto" che "numericamente non valido" in questo contesto.

Il principale "sintomo" di ciò è che, se esegui, diciamo, una media o una somma su un array contenente NaN, anche uno solo, ottieni NaN come risultato ...

D'altra parte, non è possibile eseguire operazioni matematiche utilizzando Nonecome operando.

Quindi, a seconda dei casi, potresti usare Nonecome un modo per dire al tuo algoritmo di non considerare valori non validi o inesistenti nei calcoli. Ciò significherebbe che l'algoritmo dovrebbe testare ogni valore per vedere se lo è None.

Numpy ha alcune funzioni per evitare che i valori NaN contaminino i risultati, come nansume nan_to_numper esempio.


Sono d'accordo con te che Nessuno dovrebbe essere usato per voci inesistenti, quindi perché df=pd.readcsv('file.csv')mi da NaNvalori per le celle vuote e non None? Per quanto ne so, pd.DataFrames non è esclusivo per i numeri.
user1083734

Beh, probabilmente è una scelta di design. Suppongo che DataFrames e Series abbiano un dtype, quindi i valori non validi di dtype=floatdevono essere rappresentati da valori numerici, che NaNè e Nonenon Noneè ( è di NoneType).
heltonbiker

Inoltre, molti metodi Pandas hanno un naargomento, che ti consente di decidere quale valore utilizzerai per sostituire i valori non disponibili
heltonbiker

Ok grazie. Quindi non sto effettivamente leggendo numeri nel mio DataFrame, ma stringhe di numeri e lettere. Che tipo di controllo devo utilizzare per rilevare le celle vuote? Un assegno come; se dtype == float: ??
user1083734

Forse pubblicare un campione dei tuoi dati CSV potrebbe aiutare. Posso immaginare che, se ci sono stringhe, dtype sarebbe una stringa per l'intera colonna (serie). Ma forse se non tutte le righe hanno lo stesso numero di colonne, ti ritroverai con dati non disponibili. Penso che dovrai verificarlo.
heltonbiker

3

La funzione isnan()verifica se qualcosaè "Non un numero" e restituirà se una variabileèun numero o meno, ad esempio isnan(2)restituirebbe false

Il condizionale myVar is not Nonerestituisce se la variabile è definita o meno

Il tuo array numpy usa isnan()perché è inteso come un array di numeri e inizializza tutti gli elementi dell'array a NaNquesti elementi sono considerati "vuoti"


1
Penso isnan(2)che tornerebbe False, dato che 2 non è un NaN.
heltonbiker

Inoltre, numpy.emptynon inizializza i valori dell'array su NaN. Semplicemente non inizializza affatto i valori.
heltonbiker

5
Il corretto controllo della Nonepresenza è myVar is not None, no myVar != None.
Jaime

3
Nota che np.isnan()non è implementato per le variabili stringa, quindi se gli passi una stringa andrà in crash. Meglio usare pd.isnullche funziona con le stringhe.
Michael

-1

Di seguito sono riportate le differenze:

  • nan appartiene alla classe float
  • None appartiene alla classe NoneType

Ho trovato molto utile l'articolo seguente: https://medium.com/analytics-vidhya/dealing-with-missing-values-nan-and-none-in-python-6fc9b8fb4f31


Sebbene questo collegamento possa rispondere alla domanda, è meglio includere le parti essenziali della risposta qui e fornire il collegamento come riferimento. Le risposte di solo collegamento possono diventare non valide se la pagina collegata cambia. - Dalla recensione
A. Kootstra

@ A.Kootstra Capisco
eswara amirthan s

-3

NaNstants per NON un numero .
Nonepotrebbe rappresentare qualsiasi .

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.