¿Cómo puedo reemplazar todos los valores de NaN con ceros en una columna de un marco de datos de pandas?


458

Tengo un marco de datos como a continuación

      itm Date                  Amount 
67    420 2012-09-30 00:00:00   65211
68    421 2012-09-09 00:00:00   29424
69    421 2012-09-16 00:00:00   29877
70    421 2012-09-23 00:00:00   30990
71    421 2012-09-30 00:00:00   61303
72    485 2012-09-09 00:00:00   71781
73    485 2012-09-16 00:00:00     NaN
74    485 2012-09-23 00:00:00   11072
75    485 2012-09-30 00:00:00  113702
76    489 2012-09-09 00:00:00   64731
77    489 2012-09-16 00:00:00     NaN

cuando trato de aplicar una función a la columna Cantidad, aparece el siguiente error.

ValueError: cannot convert float NaN to integer

Intenté aplicar una función usando .isnan del Módulo de Matemáticas. Probé el atributo .replace de pandas. Probé el atributo de datos .sparse de pandas 0.9. También probé si NaN == NaN en una función. También he visto este artículo ¿Cómo reemplazo los valores de NA con ceros en un marco de datos R? mientras mira otros artículos. Todos los métodos que he probado no han funcionado o no reconocen NaN. Cualquier sugerencia o solución sería apreciada.


El único problema es que df.fill.na () no funciona si el marco de datos en el que lo está aplicando se vuelve a muestrear o se ha cortado a través de la función loc
Prince Agarwal

Respuestas:


754

Creo que DataFrame.fillna()hará esto por ti.

Enlace a Documentos para un marco de datos y para una Serie .

Ejemplo:

In [7]: df
Out[7]: 
          0         1
0       NaN       NaN
1 -0.494375  0.570994
2       NaN       NaN
3  1.876360 -0.229738
4       NaN       NaN

In [8]: df.fillna(0)
Out[8]: 
          0         1
0  0.000000  0.000000
1 -0.494375  0.570994
2  0.000000  0.000000
3  1.876360 -0.229738
4  0.000000  0.000000

Para completar los NaN en una sola columna, seleccione solo esa columna. en este caso estoy usando inplace = True para cambiar realmente el contenido de df.

In [12]: df[1].fillna(0, inplace=True)
Out[12]: 
0    0.000000
1    0.570994
2    0.000000
3   -0.229738
4    0.000000
Name: 1

In [13]: df
Out[13]: 
          0         1
0       NaN  0.000000
1 -0.494375  0.570994
2       NaN  0.000000
3  1.876360 -0.229738
4       NaN  0.000000

EDITAR:

Para evitar a SettingWithCopyWarning, use la funcionalidad integrada de columna específica:

df.fillna({1:0}, inplace=True)

1
¿Se garantiza que df[1]es una vista en lugar de una copia del DF original? Obviamente, si hay una situación rara en la que es una copia, causaría un error súper problemático. ¿Hay una declaración clara sobre eso en la documentación de los pandas?
max

@max Vea esto, podría responder a su pregunta: stackoverflow.com/questions/23296282/…
Aman

Gracias. ¿Tengo entendido que en esa respuesta un "indexador que establece" es la operación de indexación más externa (ejecutada justo antes de la asignación. Por lo tanto, cualquier asignación que solo use un solo indexador está garantizada, lo que hace que su código sea seguro?
max

1

1
el último ejemplo arroja un SettingWithCopyWarning
Sip

124

No se garantiza que el corte devuelva una vista o una copia. Tu puedes hacer

df['column'] = df['column'].fillna(value)

14
Acabo de descubrir el problema "inplace = True". Esta respuesta evita el problema y creo que es la solución más limpia presentada.
TimCera

48

Puede usar replacepara cambiar NaNa 0:

import pandas as pd
import numpy as np

# for column
df['column'] = df['column'].replace(np.nan, 0)

# for whole dataframe
df = df.replace(np.nan, 0)

# inplace
df.replace(np.nan, 0, inplace=True)

¿Solo lo reemplazará NaN? o también reemplazará el valor donde NAo NaNcomo df.fillna(0)? Estoy buscando una solución que solo reemplace el valor donde hay NaNy noNA
Shyam Bhimani

1
@ShyamBhimani debería reemplazar solo NaNes decir, valores donde np.isnanes verdadero
Anton Protopopov

23

Solo quería proporcionar un poco de actualización / caso especial, ya que parece que la gente todavía viene aquí. Si está utilizando un índice múltiple o de lo contrario está utilizando un segmentador de índices, la opción inplace = True puede no ser suficiente para actualizar el segmento que ha elegido. Por ejemplo, en un índice múltiple de nivel 2x2, esto no cambiará ningún valor (a partir de pandas 0.15):

idx = pd.IndexSlice
df.loc[idx[:,mask_1],idx[mask_2,:]].fillna(value=0,inplace=True)

El "problema" es que el encadenamiento rompe la capacidad de relleno para actualizar el marco de datos original. Puse "problema" entre comillas porque hay buenas razones para las decisiones de diseño que llevaron a no interpretar a través de estas cadenas en ciertas situaciones. Además, este es un ejemplo complejo (aunque realmente me encontré con él), pero lo mismo puede aplicarse a menos niveles de índices dependiendo de cómo se divida.

La solución es DataFrame.update:

df.update(df.loc[idx[:,mask_1],idx[[mask_2],:]].fillna(value=0))

¡Es una línea, se lee razonablemente bien (más o menos) y elimina cualquier desorden innecesario con variables intermedias o bucles mientras le permite aplicar fillna a cualquier segmento de varios niveles que desee!

Si alguien puede encontrar lugares donde esto no funciona, publíquelo en los comentarios, he estado jugando con él y mirando la fuente y parece resolver al menos mis problemas de corte de índice múltiple.


21

El siguiente código funcionó para mí.

import pandas

df = pandas.read_csv('somefile.txt')

df = df.fillna(0)

7

Manera fácil de llenar los valores faltantes: -

relleno de columnas de cadena: cuando las columnas de cadena tienen valores faltantes y valores NaN.

df['string column name'].fillna(df['string column name'].mode().values[0], inplace = True)

relleno de columnas numéricas: cuando las columnas numéricas tienen valores faltantes y valores NaN.

df['numeric column name'].fillna(df['numeric column name'].mean(), inplace = True)

llenar NaN con cero:

df['column name'].fillna(0, inplace = True)

5

También puede usar diccionarios para completar los valores NaN de las columnas específicas en el DataFrame en lugar de llenar todos los DF con un valor único.

import pandas as pd

df = pd.read_excel('example.xlsx')
df.fillna( {
        'column1': 'Write your values here',
        'column2': 'Write your values here',
        'column3': 'Write your values here',
        'column4': 'Write your values here',
        .
        .
        .
        'column-n': 'Write your values here'} , inplace=True)

Esta es la solución pensada por el desarrollador para la pregunta del OP.
johnDanger

4

ingrese la descripción de la imagen aquí

Teniendo en cuenta que la columna particular Amounten la tabla anterior es de tipo entero. Lo siguiente sería una solución:

df['Amount'] = df.Amount.fillna(0).astype(int)

Del mismo modo, puede llenarlo con varios tipos de datos como float, stretc.

En particular, consideraría el tipo de datos para comparar varios valores de la misma columna.


2

Para reemplazar los valores na en pandas

df['column_name'].fillna(value_to_be_replaced,inplace=True)

si inplace = False, en lugar de actualizar el df (marco de datos), devolverá los valores modificados.


1

Si fuera a convertirlo en un marco de datos de pandas, también puede lograr esto usando fillna.

import numpy as np
df=np.array([[1,2,3, np.nan]])

import pandas as pd
df=pd.DataFrame(df)
df.fillna(0)

Esto devolverá lo siguiente:

     0    1    2   3
0  1.0  2.0  3.0 NaN
>>> df.fillna(0)
     0    1    2    3
0  1.0  2.0  3.0  0.0

1

Hay dos opciones disponibles principalmente; en caso de imputación o llenado de valores faltantes NaN / np.nan con solo reemplazos numéricos (a través de las columnas:

df['Amount'].fillna(value=None, method= ,axis=1,) es suficiente:

De la documentación:

valor: escalar, dict, Series o DataFrame Valor para usar para rellenar huecos (por ejemplo, 0), alternativamente un dict / Series / DataFrame de valores que especifican qué valor usar para cada índice (para una Serie) o columna (para un DataFrame) . (los valores que no están en dict / Series / DataFrame no se completarán). Este valor no puede ser una lista.

Lo que significa que 'cadenas' o 'constantes' ya no se pueden imputar.

Para imputaciones más especializadas, use SimpleImputer () :

from sklearn.impute import SimpleImputer
si = SimpleImputer(strategy='constant', missing_values=np.nan, fill_value='Replacement_Value')
df[['Col-1', 'Col-2']] = si.fit_transform(X=df[['C-1', 'C-2']])

0

Para reemplazar nan en diferentes columnas con diferentes formas:

   replacement= {'column_A': 0, 'column_B': -999, 'column_C': -99999}
   df.fillna(value=replacement)
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.