¿Cuál es la diferencia entre NaN y None?

94

Estoy leyendo dos columnas de un archivo csv usando pandas readcsv()y luego asignando los valores a un diccionario. Las columnas contienen cadenas de números y letras. Ocasionalmente, hay casos en los que una celda está vacía. En mi opinión, el valor leído en esa entrada del diccionario debería ser Nonepero en su lugar nanestá asignado. Seguramente Nonees más descriptivo de una celda vacía ya que tiene un valor nulo, mientras quenan simplemente dice que el valor leído no es un número.

¿Mi comprensión es correcta, cuál ES la diferencia entre Noney nan? ¿Por qué se nanasigna en lugar deNone ?

Además, mi verificación de diccionario en busca de celdas vacías ha estado usando numpy.isnan():

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

Pero esto me da un error que dice que no puedo usar esta verificación para v. Supongo que se debe a que se debe usar una variable entera o flotante, no una cadena. Si esto es cierto, ¿cómo puedo verificar si hay vuna "celda vacía" / nancaso?

usuario1083734
fuente
El texto qwertyno es un número.
Robert Harvey
1
@RobertHarvey Lo sé, así que seguramente Nonesería una mejor descripción del valor de una celda vacía.
user1083734

Respuestas:

107

NaN se usa como un marcador de posición para los datos faltantes de manera consistente en pandas , la consistencia es buena. Normalmente leo / traduzco NaN como "perdido" . También vea la sección 'trabajar con datos faltantes' en los documentos.

Wes escribe en los documentos 'elección de la representación de NA' :

Después de años de producción, el uso [NaN] ha demostrado, al menos en mi opinión, ser la mejor decisión dada la situación en NumPy y Python en general. El valor especial NaN (No-A-Number) se utiliza en todas partes como el valor NA, y hay funciones de API isnully notnullque puede ser utilizado en todos los dtypes para detectar valores de NA.
...
Por lo tanto, he elegido el enfoque Pythonic de "practicidad vence a la pureza" y la capacidad NA de enteros intercambiados por un enfoque mucho más simple de usar un valor especial en arreglos flotantes y de objetos para denotar NA, y promover arreglos enteros a flotantes cuando los NA deben ser introducido.

Nota: el "gotcha" de que las series enteras que contienen datos faltantes son upcast a flotantes .

En mi opinión, la razón principal para usar NaN (en lugar de None) es que se puede almacenar con el tipo dtype float64 de numpy, en lugar del dtype de objeto menos eficiente, consulte las promociones de 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 comenta (abajo) sobre esto:

np.nanpermite operaciones vectorizadas; es un valor flotante, mientras que None, por definición, fuerza el tipo de objeto, que básicamente desactiva toda la eficiencia en numpy.

Entonces repita 3 veces rápido: objeto == malo, flotar == bueno

Dicho esto, muchas operaciones pueden funcionar igual de bien con None vs NaN (pero quizás no sean compatibles, es decir, a veces pueden dar resultados sorprendentes ):

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

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

Para responder a la segunda pregunta:
debería utilizar pd.isnully pd.notnullpara probar los datos faltantes (NaN).

Andy Hayden
fuente
19
simplemente agregando 2c aquí .... np.nanpermite operaciones vectorizadas; es un valor flotante, mientras que Nonepor definición fuerza el objecttipo, y básicamente deshabilita toda la eficiencia en numpy, así que repita 3 veces rápido:object==bad, float==good
Jeff
1
¿ <NA>También es un np.nan?
Gathide
18

NaNse puede utilizar como valor numérico en operaciones matemáticas, mientras Noneque no se puede (o al menos no debería).

NaNes un valor numérico, como se define en el estándar de coma flotante IEEE 754 . Nonees un tipo interno de Python (NoneType ) y sería más como "inexistente" o "vacío" que "numéricamente no válido" en este contexto.

El principal "síntoma" de eso es que, si realiza, digamos, un promedio o una suma en una matriz que contiene NaN, incluso uno solo, obtiene NaN como resultado ...

Por otro lado, no puede realizar operaciones matemáticas utilizando Nonecomo operando.

Entonces, dependiendo del caso, puede usarlo Nonecomo una forma de decirle a su algoritmo que no considere valores inválidos o inexistentes en los cálculos. Eso significaría que el algoritmo debería probar cada valor para ver si lo es None.

Numpy tiene algunas funciones para evitar que los valores de NaN contaminen sus resultados, como nansumy nan_to_numpor ejemplo.

heltonbiker
fuente
Estoy de acuerdo con usted en que Ninguno debe usarse para entradas inexistentes, entonces, ¿por qué df=pd.readcsv('file.csv')me da NaNvalores para las celdas vacías y no None? Hasta donde yo sé, pd.DataFrames no son exclusivos de los números.
user1083734
Bueno, probablemente sea una elección de diseño. Supongo que DataFrames y Series tienen un dtype, por lo que los valores no válidos de dtype=floatdeben estar representados por valores numéricos, que NaNes y Noneno Nonees ( es NoneType).
heltonbiker
Además, muchos métodos de Pandas tienen un naargumento, que le permite decidir qué valor va a utilizar para reemplazar los valores no disponibles
heltonbiker
OK gracias. Entonces, en realidad, no estoy leyendo números en mi DataFrame, sino cadenas de números y letras. ¿Qué tipo de verificación debería usar para detectar celdas vacías? Un cheque como; if dtype == float: ??
user1083734
Quizás sería útil publicar una muestra de sus datos CSV. Puedo imaginar que, si hay cadenas, dtype sería una cadena para toda la columna (Serie). Pero quizás si no todas las filas tienen el mismo número de columnas, terminará con datos no disponibles. Creo que tendrás que comprobarlo.
heltonbiker
3

La función isnan()comprueba si algo es "No es un número" y devolverá si una variable es un número o no, por ejemplo isnan(2), devolvería falso

El condicional myVar is not Nonedevuelve si la variable está definida o no

Su matriz numpy utiliza isnan()porque está destinada a ser una matriz de números e inicializa todos los elementos de la matriz para que NaNestos elementos se consideren "vacíos"

Stephan
fuente
1
Creo isnan(2)que volvería False, ya que 2 no es un NaN.
heltonbiker
Además, numpy.emptyno inicializa los valores de la matriz en NaN. Simplemente no inicializa los valores en absoluto.
heltonbiker
5
La verificación adecuada de la Nonecondición es myVar is not None, no myVar != None.
Jaime
3
Tenga en cuenta que np.isnan()no está implementado para variables de cadena, por lo que si le pasa una cadena, se bloqueará. Es mejor usar el pd.isnullque funciona con cadenas.
Michael
-1

A continuación se muestran las diferencias:

  • nan pertenece a la clase float
  • None pertenece a la clase NoneType

Encontré el siguiente artículo muy útil: https://medium.com/analytics-vidhya/dealing-with-missing-values-nan-and-none-in-python-6fc9b8fb4f31

eswara amirthan s
fuente
Si bien este enlace puede responder la pregunta, es mejor incluir aquí las partes esenciales de la respuesta y proporcionar el enlace como referencia. Las respuestas de solo enlace pueden dejar de ser válidas si cambia la página enlazada. - De la opinión
A. Kootstra
@ A.Kootstra Lo entiendo
eswara amirthan s
-3

NaNsignifica NO un número .
Nonepodría representar cualquiera .

diegoaguilar
fuente