Marco de datos de pandas fillna () solo algunas columnas en su lugar


145

Estoy tratando de completar ninguno de los valores en un marco de datos de Pandas con 0 para solo un subconjunto de columnas.

Cuando lo hago:

import pandas as pd
df = pd.DataFrame(data={'a':[1,2,3,None],'b':[4,5,None,6],'c':[None,None,7,8]})
print df
df.fillna(value=0, inplace=True)
print df

La salida:

     a    b    c
0  1.0  4.0  NaN
1  2.0  5.0  NaN
2  3.0  NaN  7.0
3  NaN  6.0  8.0
     a    b    c
0  1.0  4.0  0.0
1  2.0  5.0  0.0
2  3.0  0.0  7.0
3  0.0  6.0  8.0

Reemplaza cada uno Nonecon 0's. Lo que quiero hacer es, solo reemplazar Nones en columnas ay b, pero no c.

Cual es la mejor manera de hacer esto?

Respuestas:


219

Puede seleccionar sus columnas deseadas y hacerlo por asignación:

df[['a', 'b']] = df[['a','b']].fillna(value=0)

El resultado resultante es el esperado:

     a    b    c
0  1.0  4.0  NaN
1  2.0  5.0  NaN
2  3.0  0.0  7.0
3  0.0  6.0  8.0

Sí, esto es exactamente lo que quiero! Gracias. ¿Alguna forma de hacer esto en el lugar? Mi marco de datos original es bastante grande.
Dijo el

1
No creo que haya ningún aumento de rendimiento al hacer esto en su lugar, ya que de todos modos está sobrescribiendo el df original
EdChum

44
El lugar es superfluo aquí, df[['a', 'b']] = df[['a','b']].fillna(value=0)seguirá funcionando
EdChum

2
@EdChum ¿No produce un marco de datos temporal y, por lo tanto, necesita más memoria para hacerlo? (Me preocupa más la memoria que la complejidad del tiempo.)
Sait

77
Para muchas operaciones, inplaceseguirá funcionando en una copia. No sé si es el caso fillnao no. Vea esta respuesta de uno de los desarrolladores principales de pandas.
root

85

Puede usar dict, fillnacon diferentes valores para diferentes columnas

df.fillna({'a':0,'b':0})
Out[829]: 
     a    b    c
0  1.0  4.0  NaN
1  2.0  5.0  NaN
2  3.0  0.0  7.0
3  0.0  6.0  8.0

Después de asignarlo de nuevo

df=df.fillna({'a':0,'b':0})
df
Out[831]: 
     a    b    c
0  1.0  4.0  NaN
1  2.0  5.0  NaN
2  3.0  0.0  7.0
3  0.0  6.0  8.0

1
realmente genial, por cierto para el dict que puedes usar fromkeyssi quieres, +1
U10-Forward

1
La respuesta / ejemplo sería más claro si en realidad mostrara diferentes valores para las diferentes columnas.
RufusVS

@RufusVS es correcto, pero aún así intenta igualar la salida esperada de la
operación

1
Esta es la mejor solución que la respuesta aceptada, ya que evita problemas de indexación encadenada, por ejemplo, si se usa condf.fillna({'a':0,'b':0}, inplace=True)
Alex

19

Puede evitar hacer una copia del objeto utilizando la solución de Wen e inplace = True:

df.fillna({'a':0, 'b':0}, inplace=True)
print(df)

Cuyos rendimientos:

     a    b    c
0  1.0  4.0  NaN
1  2.0  5.0  NaN
2  3.0  0.0  7.0
3  0.0  6.0  8.0

1
Si bien esto es correcto, evitar una copia no es necesariamente mejor .
jpp

7

Así es como puedes hacerlo todo en una línea:

df[['a', 'b']].fillna(value=0, inplace=True)

Desglose: df[['a', 'b']]selecciona las columnas para las que desea llenar los valores de NaN, value=0le dice que llene los NaN con cero y inplace=Truehará los cambios permanentes, sin tener que hacer una copia del objeto.


7

el uso de la respuesta superior produce una advertencia sobre la realización de cambios en una copia de un segmento df Suponiendo que tiene otras columnas, una mejor manera de hacerlo es pasar un diccionario:
df.fillna({'A': 'NA', 'B': 'NA'}, inplace=True)


3

O algo como:

df.loc[df['a'].isnull(),'a']=0
df.loc[df['b'].isnull(),'b']=0

y si hay más:

for i in your_list:
    df.loc[df[i].isnull(),i]=0

0

Algunas veces esta sintaxis no funciona:

df[['col1','col2']] = df[['col1','col2']].fillna()

Use lo siguiente en su lugar:

df['col1','col2']
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.