Popatrzmy na takie polecenie:
1 2 3 4 5 6 7 |
import pandas as pd <span class="pln">df </span><span class="pun">=</span><span class="pln"> pd</span><span class="pun">.</span><span class="typ">DataFrame</span><span class="pun">({</span><span class="str">'Name'</span><span class="pun">:[</span><span class="str">'Jack'</span><span class="pun">,</span><span class="str">'Sue'</span><span class="pun">,</span><span class="pln">pd</span><span class="pun">.</span><span class="pln">np</span><span class="pun">.</span><span class="pln">nan</span><span class="pun">,</span><span class="str">'Bob'</span><span class="pun">,</span><span class="str">'Alice'</span><span class="pun">,</span><span class="str">'John'</span><span class="pun">],</span> <span class="str">'A'</span><span class="pun">:</span> <span class="pun">[</span><span class="lit">1</span><span class="pun">,</span> <span class="lit">2.1</span><span class="pun">,</span><span class="pln"> pd</span><span class="pun">.</span><span class="pln">np</span><span class="pun">.</span><span class="pln">nan</span><span class="pun">,</span> <span class="lit">4.7</span><span class="pun">,</span> <span class="lit">5.6</span><span class="pun">,</span> <span class="lit">6.8</span><span class="pun">],</span> <span class="str">'B'</span><span class="pun">:</span> <span class="pun">[.</span><span class="lit">25</span><span class="pun">,</span><span class="pln"> pd</span><span class="pun">.</span><span class="pln">np</span><span class="pun">.</span><span class="pln">nan</span><span class="pun">,</span><span class="pln"> pd</span><span class="pun">.</span><span class="pln">np</span><span class="pun">.</span><span class="pln">nan</span><span class="pun">,</span> <span class="lit">4</span><span class="pun">,</span> <span class="lit">12.2</span><span class="pun">,</span> <span class="lit">14.4</span><span class="pun">],</span> <span class="str">'City'</span><span class="pun">:[</span><span class="str">'Seattle'</span><span class="pun">,</span><span class="str">'SF'</span><span class="pun">,</span><span class="str">'LA'</span><span class="pun">,</span><span class="str">'OC'</span><span class="pun">,</span><span class="pln">pd</span><span class="pun">.</span><span class="pln">np</span><span class="pun">.</span><span class="pln">nan</span><span class="pun">,</span><span class="pln">pd</span><span class="pun">.</span><span class="pln">np</span><span class="pun">.</span><span class="pln">nan</span><span class="pun">]})</span> 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:
1 |
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
1 2 3 4 5 |
<span class="kwd">def</span><span class="pln"> do_something</span><span class="pun">(</span><span class="pln">df</span><span class="pun">):</span> <span class="pln"> foo </span><span class="pun">=</span><span class="pln"> df</span><span class="pun">[[</span><span class="str">'bar'</span><span class="pun">,</span> <span class="str">'baz'</span><span class="pun">]]</span> <span class="com"># Is foo a view? A copy? Nobody knows!</span> <span class="com"># ... many lines here ...</span> <span class="pln"> foo</span><span class="pun">[</span><span class="str">'quux'</span><span class="pun">]</span> <span class="pun">=</span><span class="pln"> value </span><span class="com"># We don't know whether this will modify df or not!</span> <span class="kwd">return</span><span class="pln"> foo</span> |
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