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?

Sait
fuente

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
raíz
fuente
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
YOBEN_S
fuente
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
Leesa H.
fuente
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.

Josephine M. Ho
fuente
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)

Jonathan
fuente
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
U10-Adelante
fuente
0

Algunas veces esta sintaxis no funciona:

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

Use lo siguiente en su lugar:

df['col1','col2']
Sarath Baby
fuente