Pandy dataframe fillna () tylko niektóre kolumny na miejscu

145

Próbuję wypełnić żadne wartości w ramce danych Pandas z zerami tylko dla niektórych podzbiorów kolumn.

Kiedy robię:

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

Wyjście:

     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

Zastępuje każdy Nonez 0. Chcę tylko zamienić Nones w kolumnach ai b, ale nie c.

Jaki jest najlepszy sposób na zrobienie tego?

Sait
źródło

Odpowiedzi:

219

Możesz wybrać żądane kolumny i zrobić to przez przypisanie:

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

Wynikowy wynik jest zgodny z oczekiwaniami:

     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
korzeń
źródło
Tak, właśnie tego chcę! Dziękuję Ci. Jakieś sposoby, aby to zrobić w miejscu? Moja oryginalna ramka danych jest dość duża.
Sait
1
Nie wydaje mi się, aby robienie tego na miejscu
przyniosło
4
Lokacja jest tutaj zbędna, df[['a', 'b']] = df[['a','b']].fillna(value=0)nadal będzie działać
EdChum
2
@EdChum Czy nie tworzy tymczasowej ramki danych i dlatego potrzebuje do tego więcej pamięci? (Bardziej martwi mnie pamięć niż złożoność czasowa.)
Sait
7
W przypadku wielu operacji inplacenadal będzie działać na kopii. Nie wiem, czy tak jest, fillnaczy nie. Zobacz odpowiedź jednego z głównych twórców pand.
root
85

Możesz użyć dict, fillnaz inną wartością dla różnych kolumn

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

Po przypisaniu go z powrotem

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
źródło
1
naprawdę fajne, przy okazji dyktowanie, którego możesz użyć, fromkeysjeśli chcesz, +1
U10-Forward
1
Odpowiedź / przykład byłaby jaśniejsza, gdyby faktycznie pokazywała różne wartości dla różnych kolumn.
RufusVS
@RufusVS to prawda, ale nadal staraj się dopasować oczekiwany wynik
operacji
1
Jest to lepsze rozwiązanie niż zaakceptowana odpowiedź, ponieważ pozwala uniknąć problemów związanych z indeksowaniem łańcuchowym, np. Jeśli jest używany zdf.fillna({'a':0,'b':0}, inplace=True)
Alex
19

Możesz uniknąć tworzenia kopii obiektu za pomocą rozwiązania Wen i inplace = True:

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

Co daje:

     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.
źródło
1
Chociaż jest to poprawne, unikanie kopii niekoniecznie jest lepsze .
jpp
7

Oto, jak możesz to wszystko zrobić w jednej linii:

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

Podział: df[['a', 'b']]wybiera kolumny, dla których chcesz wypełnić wartości NaN, value=0mówi mu, aby wypełnić pola NaN zerami i inplace=Truesprawi, że zmiany będą trwałe, bez konieczności wykonywania kopii obiektu.

Josephine M. Ho
źródło
7

użycie pierwszej odpowiedzi powoduje wyświetlenie ostrzeżenia o dokonywaniu zmian w kopii wycinka df. Zakładając, że masz inne kolumny, lepszym sposobem na to jest przekazanie słownika:
df.fillna({'A': 'NA', 'B': 'NA'}, inplace=True)

Jonathan
źródło
3

Lub coś takiego:

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

a jeśli jest więcej:

for i in your_list:
    df.loc[df[i].isnull(),i]=0
U10-Forward
źródło
0

Czasami ta składnia nie działa:

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

Zamiast tego użyj następujących:

df['col1','col2']
Sarath Baby
źródło