Python: Pandas: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame

25-Lis-2018

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

Dodaj komentarz:

Autor: Rafał Kraik