¿Hay algún método para reemplazar valores Noneen Pandas en Python?
Puede usar df.replace('pre', 'post')y puede reemplazar un valor con otro, pero esto no se puede hacer si desea reemplazarlo con un Nonevalor, que si lo intenta, obtendrá un resultado extraño.
Así que aquí tienes un ejemplo:
df = DataFrame(['-',3,2,5,1,-5,-1,'-',9])
df.replace('-', 0)
que devuelve un resultado exitoso.
Pero,
df.replace('-', None)
que devuelve el siguiente resultado:
0
0 - // this isn't replaced
1 3
2 2
3 5
4 1
5 -5
6 -1
7 -1 // this is changed to `-1`...
8 9
¿Por qué se devuelve un resultado tan extraño?
Como quiero verter este marco de datos en la base de datos MySQL, no puedo poner NaNvalores en ningún elemento en mi marco de datos y en su lugar quiero poner None. Seguramente, primero puede cambiar '-'a NaNy luego convertir NaNa None, pero quiero saber por qué la trama de datos actúa de una manera tan terrible.
Probado en pandas 0.12.0 dev en Python 2.7 y OS X 10.8. Python es una versión preinstalada en OS X e instalé pandas usando el script SciPy Superpack, para su información.

write_frameNo analizaNaNs anones?InternalError: (1054, u"Unknown column 'nan' in 'field list'")error. No sé acerca de cualquier soluciones en él distintos de la conversiónNaNaNoneantes de ejecutarwrite_frameel método.na_valuesargumento. Más información en esta respuesta.Respuestas:
En realidad, en versiones posteriores de pandas, esto dará un TypeError:
df.replace('-', None) TypeError: If "to_replace" and "value" are both None then regex must be a mappingPuede hacerlo pasando una lista o un diccionario:
In [11]: df.replace('-', df.replace(['-'], [None]) # or .replace('-', {0: None}) Out[11]: 0 0 None 1 3 2 2 3 5 4 1 5 -5 6 -1 7 None 8 9Pero recomiendo usar NaN en lugar de Ninguno:
In [12]: df.replace('-', np.nan) Out[12]: 0 0 NaN 1 3 2 2 3 5 4 1 5 -5 6 -1 7 NaN 8 9fuente
df.replace(['-'], [None]), odf.replace({'-': None}), creo. El uso deNonecomo centinela también excluye su uso como valor ..dfnuevo a sí mismo como:df = df.replace({'?': np.nan})df.replace('-', df.replace(['-'], [None])ve raro , ¿es un error tipográfico?Prefiero la solución que usa
replacecon adictpor su sencillez y elegancia:df.replace({'-': None})También puede tener más reemplazos:
df.replace({'-': None, 'None': None})E incluso para reemplazos más grandes, siempre es obvio y claro qué se reemplaza por qué, lo que es mucho más difícil para listas largas, en mi opinión.
fuente
dicttipo into_replacehace que elmethodparámetro no se evalúe y, por lo tanto, elmethod='pad'valor predeterminado no tenga efectos nocivos.wherees probablemente lo que estás buscando. Entoncesdata=data.where(data=='-', None)De los documentos de panda :
fuente
Antes de continuar con esta publicación, es importante comprender la diferencia entre NaN y None . Uno es un tipo flotante, el otro es un tipo de objeto. Pandas es más adecuado para trabajar con tipos escalares, ya que se pueden vectorizar muchos métodos en estos tipos. Pandas intenta manejar None y NaN de manera consistente, pero NumPy no puede.
Mi sugerencia ( y la de Andy ) es seguir con NaN.
Pero para responder a tu pregunta ...
pandas> = 0.18: Use
na_values=['-']argumento conread_csvSi cargó estos datos desde CSV / Excel, tengo buenas noticias para usted. Puede anular esto en la raíz durante la carga de datos en lugar de tener que escribir una solución con código como paso posterior.
La mayoría de las
pd.read_*funciones (comoread_csvyread_excel) aceptan unna_valuesatributo.file.csvA,B -,1 3,- 2,- 5,3 1,-2 -5,4 -1,-1 -,0 9,0Ahora, para convertir los
-caracteres en NaN, haga,import pandas as pd df = pd.read_csv('file.csv', na_values=['-']) df A B 0 NaN 1.0 1 3.0 NaN 2 2.0 NaN 3 5.0 3.0 4 1.0 -2.0 5 -5.0 4.0 6 -1.0 -1.0 7 NaN 0.0 8 9.0 0.0Y similar para otras funciones / formatos de archivo.
PD: en v0.24 +, puede conservar el tipo de entero incluso si su columna tiene NaN (sí, hable de tener el pastel y comérselo también). Puede especificar
dtype='Int32'df = pd.read_csv('file.csv', na_values=['-'], dtype='Int32') df A B 0 NaN 1 1 3 NaN 2 2 NaN 3 5 3 4 1 -2 5 -5 4 6 -1 -1 7 NaN 0 8 9 0 df.dtypes A Int32 B Int32 dtype: objectEl dtype no es un tipo int convencional ... sino más bien, un tipo entero que acepta valores NULL. Hay otras opciones.
Manejo de datos numéricos:
pd.to_numericconerrors='coerceSi está tratando con datos numéricos, una solución más rápida es usar
pd.to_numericcon elerrors='coerce'argumento, que coacciona valores no válidos (valores que no se pueden convertir en numéricos) a NaN.pd.to_numeric(df['A'], errors='coerce') 0 NaN 1 3.0 2 2.0 3 5.0 4 1.0 5 -5.0 6 -1.0 7 NaN 8 9.0 Name: A, dtype: float64Para retener (nullable) dtype entero, use
pd.to_numeric(df['A'], errors='coerce').astype('Int32') 0 NaN 1 3 2 2 3 5 4 1 5 -5 6 -1 7 NaN 8 9 Name: A, dtype: Int32Para coaccionar varias columnas, use
apply:df[['A', 'B']].apply(pd.to_numeric, errors='coerce').astype('Int32') A B 0 NaN 1 1 3 NaN 2 2 NaN 3 5 3 4 1 -2 5 -5 4 6 -1 -1 7 NaN 0 8 9 0... y asigne el resultado de nuevo después.
Puede encontrar más información en esta respuesta .
fuente
df = pd.DataFrame(['-',3,2,5,1,-5,-1,'-',9]) df = df.where(df!='-', None)fuente
La configuración de valores nulos se puede hacer con
np.nan:import numpy as np df.replace('-', np.nan)La ventaja es que las
df.last_valid_index()reconoce como inválidas.fuente
Usando reemplazar y asignando un nuevo df:
import pandas as pd df = pd.DataFrame(['-',3,2,5,1,-5,-1,'-',9]) dfnew = df.replace('-', 0) print(dfnew) (venv) D:\assets>py teste2.py 0 0 0 1 3 2 2 3 5 4 1 5 -5fuente
df.replace('-', np.nan).astype("object")Esto asegurará que pueda usar
isnull()más adelante en su marco de datosfuente
Con la versión de Pandas ≥1.0.0, usaría
DataFrame.replaceoSeries.replace:df.replace(old_val, pd.NA, inplace=True)Esto es mejor por dos razones:
pd.NAlugar deNoneonp.nan.fuente