Pandaas dataframe fillna () solo alcune colonne sul posto


145

Sto cercando di riempire nessuno dei valori in un frame di dati Pandas con 0 per solo un sottoinsieme di colonne.

Quando io faccio:

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

Il risultato:

     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

Sostituisce ogni Nonecon 0's. Quello che voglio fare è sostituire solo le Nones nelle colonne ae b, ma non c.

Qual è il modo migliore per fare questo?

Risposte:


219

È possibile selezionare le colonne desiderate e farlo assegnando:

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

L'output risultante è come previsto:

     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ì, questo è esattamente quello che voglio! Grazie. Qualche modo per farlo sul posto? Il mio frame di dati originale è piuttosto grande.
Ha detto il

1
Non penso che ci sia alcun miglioramento delle prestazioni facendo questo sul posto mentre stai sovrascrivendo comunque l'orig df
EdChum

4
La loc è superflua qui, df[['a', 'b']] = df[['a','b']].fillna(value=0)funzionerà ancora
EdChum

2
@EdChum Non produce un frame di dati temporaneo e quindi ha bisogno di più memoria per farlo? (Mi preoccupo più della memoria che della complessità del tempo.)
Diceva il

7
Per molte operazioni, inplacefunzionerà comunque su una copia. Non so se è il caso fillnao no. Vedi questa risposta da uno degli sviluppatori principali di Panda.
radice

86

È possibile utilizzare dict, fillnacon valore diverso per colonna diversa

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

Dopo averlo assegnato di nuovo

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
davvero fantastico, tra il dict che puoi usare fromkeysse vuoi, +1
U10-Forward

1
La risposta / esempio sarebbe più chiara se effettivamente mostrasse valori diversi per le diverse colonne.
RufusVS,

@RufusVS è giusto, ma provo ancora a corrispondere all'output previsto
dell'operazione

1
Questa è la soluzione migliore che la risposta accettata, perché evita problemi di indicizzazione concatenati, ad esempio se utilizzato condf.fillna({'a':0,'b':0}, inplace=True)
Alex

19

Puoi evitare di fare una copia dell'oggetto usando la soluzione di Wen e inplace = True:

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

Che produce:

     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
Sebbene ciò sia corretto, evitare una copia non è necessariamente migliore .
jpp

7

Ecco come puoi fare tutto in una riga:

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

Ripartizione: df[['a', 'b']]seleziona le colonne per cui vuoi riempire i valori NaN, gli value=0dice di riempire NaNs con zero e inplace=Truerenderà permanenti le modifiche, senza dover fare una copia dell'oggetto.


7

l'utilizzo della risposta superiore produce un avvertimento su come apportare modifiche a una copia di una porzione df. Supponendo di avere altre colonne, un modo migliore per farlo è passare un dizionario:
df.fillna({'A': 'NA', 'B': 'NA'}, inplace=True)


3

O qualcosa del genere:

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

e se c'è di più:

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

0

A volte questa sintassi non funziona:

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

Utilizzare invece quanto segue:

df['col1','col2']
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.