¿Hay algún método para reemplazar valores None
en 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 None
valor, 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 NaN
valores en ningún elemento en mi marco de datos y en su lugar quiero poner None
. Seguramente, primero puede cambiar '-'
a NaN
y luego convertir NaN
a 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_frame
No analizaNaN
s anone
s?InternalError: (1054, u"Unknown column 'nan' in 'field list'")
error. No sé acerca de cualquier soluciones en él distintos de la conversiónNaN
aNone
antes de ejecutarwrite_frame
el método.na_values
argumento. 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 mapping
Puede 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 9
Pero 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 9
fuente
df.replace(['-'], [None])
, odf.replace({'-': None})
, creo. El uso deNone
como centinela también excluye su uso como valor ..df
nuevo 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
replace
con adict
por 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
dict
tipo into_replace
hace que elmethod
parámetro no se evalúe y, por lo tanto, elmethod='pad'
valor predeterminado no tenga efectos nocivos.where
es 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_csv
Si 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_csv
yread_excel
) aceptan unna_values
atributo.file.csv
A,B -,1 3,- 2,- 5,3 1,-2 -5,4 -1,-1 -,0 9,0
Ahora, 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.0
Y 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: object
El 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_numeric
conerrors='coerce
Si está tratando con datos numéricos, una solución más rápida es usar
pd.to_numeric
con 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: float64
Para 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: Int32
Para 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 -5
fuente
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.replace
oSeries.replace
:df.replace(old_val, pd.NA, inplace=True)
Esto es mejor por dos razones:
pd.NA
lugar deNone
onp.nan
.fuente