Popatrzmy na takie polecenie:
import pandas as pd
df = pd.DataFrame({'Name':['Jack','Sue',pd.np.nan,'Bob','Alice','John'],
'A': [1, 2.1, pd.np.nan, 4.7, 5.6, 6.8],
'B': [.25, pd.np.nan, pd.np.nan, 4, 12.2, 14.4],
'City':['Seattle','SF','LA','OC',pd.np.nan,pd.np.nan]})
df[['A','B']].fillna('?', inplace=True)
wynik to niestety ostrzeżenie:
SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame
See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
downcast=downcast, **kwargs)
Kiedy funkcja zwraca kopię danych i na tej kopii chcesz wykonać następne polecenie, to zmiany wykonane na kopii będą istnieć tylko tak długo jak istnieje kopia tych danych. Teraz mamy kilka problemów:
-niektóre podobne operatory są oprogramowane na różne sposoby, a my jako tylko użytkownicy tych funkcji nie znamy ich wewnętrznej budowy – nic dziwnego, że popełniamy błędy!
-skorzystanie lub ominięcie inplace powoduje, że funkcja zadziała w ten a nie w inny sposób. Dokładniej inplace=True oznacza że operacja ma być wykonana na danym obiekcie, który może być taką krótkotrwałą kopią. inplace=False oznacza, że wynik ma być zwrócony, więc nie ma obawy o zaktualizowanie krótkotrwałej kopii.
W tym przypadku myślę sobie „acha – df[[’A’,’B’]] zwraca kopię, a inplace mówi, że zmiana ma być wykonana na TYM obiekcie, a więc na kopii” i wtedy usuwam inplace – żeby zmiana nie była wykonana na kopii, a przepisanie wyniku do oryginalnego obiektu biorę na siebie o tak:
df[['A','B']] = df[['A','B']].fillna('?')
Mam wrażenie, że Pythonowcy sami się z tego trochę śmieją…, cytat ze strony: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
def do_something(df): foo = df[['bar', 'baz']] # Is foo a view? A copy? Nobody knows! # ... many lines here ... foo['quux'] = value # We don't know whether this will modify df or not! return foo
Podsumowując: inplace powoduje, że modyfikowana jest ulotna kopia, która za moment zniknie – stąd error/warning. Kiedy rezygnujesz z inplace, to oczekujesz, że metoda zwróci kopię danych, a ty sam w swoim skrypcie decydujesz, co z tą kopią zrobisz – zazwyczaj wpisujesz w to samo miejsce w oryginalnym obiekcie