Podczas wybierania podrzędnej ramki danych z nadrzędnej ramki danych zauważyłem, że niektórzy programiści wykonują kopię ramki danych za pomocą tej .copy()
metody. Na przykład,
X = my_dataframe[features_list].copy()
... zamiast po prostu
X = my_dataframe[features_list]
Dlaczego robią kopię ramki danych? Co się stanie, jeśli nie wykonam kopii?
python
pandas
chained-assignment
Elizabeth Susan Joseph
źródło
źródło
Odpowiedzi:
To rozszerza odpowiedź Pawła. W Pandas indeksowanie DataFrame zwraca odwołanie do początkowej DataFrame. W związku z tym zmiana podzbioru spowoduje zmianę początkowej ramki DataFrame. Dlatego chcesz użyć kopii, jeśli chcesz mieć pewność, że początkowa ramka DataFrame nie ulegnie zmianie. Rozważ następujący kod:
Dostaniesz:
Natomiast następujące pozostawia df niezmienione:
źródło
Ponieważ jeśli nie wykonasz kopii, indeksy nadal można manipulować w innym miejscu, nawet jeśli przypiszesz element dataFrame do innej nazwy.
Na przykład:
func1 może modyfikować df poprzez modyfikację df2, aby tego uniknąć:
źródło
, both variables reference the same DataFrame instance. So any changes made to
” lubdf2
zostanie przypisane do tej samej instancji obiektu. Podczas gdy wdf2 = df.copy()
drugiej instancji obiektu jest tworzona kopia pierwszej instancji, ale terazdf
idf2
odniesienie do różnych instancji obiektów i wszelkie zmiany zostaną wprowadzone do ich odpowiednich instancji DataFrame.Należy wspomnieć, że zwrócenie kopii lub widoku zależy od rodzaju indeksowania.
Dokumentacja pand mówi:
źródło
Głównym celem jest uniknięcie indeksowania łańcuchowego i wyeliminowanie
SettingWithCopyWarning
.Tutaj jest coś w rodzaju indeksowania łańcuchowego
dfc['A'][0] = 111
Dokument mówiący o tym, że indeksowanie łańcuchowe powinno być unikane w sekcji Zwracanie widoku a kopia . Oto nieco zmodyfikowany przykład z tego dokumentu:
Tutaj
aColumn
jest to widok, a nie kopia z oryginalnej ramki DataFrame, więc modyfikacjaaColumn
spowoduje równieżdfc
zmodyfikowanie oryginału . Następnie, jeśli najpierw zindeksujemy wiersz:Tym razem
zero_row
jest to kopia, więc oryginałdfc
nie jest modyfikowany.Z tych dwóch przykładów powyżej widzimy, że nie jest jednoznaczne, czy chcesz zmienić oryginalną ramkę DataFrame. Jest to szczególnie niebezpieczne, jeśli napiszesz coś takiego:
Tym razem w ogóle się nie udało. Tutaj chcieliśmy zmienić
dfc
, ale tak naprawdę zmodyfikowaliśmy wartość pośrednią,dfc.loc[0]
która jest kopią i jest natychmiast odrzucana. Bardzo trudno jest przewidzieć, czy wartość pośrednia, taka jak widok lub kopia,dfc.loc[0]
czy teżdfc['A']
jest widokiem lub kopią, więc nie ma gwarancji, czy oryginalna ramka DataFrame zostanie zaktualizowana. Dlatego należy unikać indeksowania łańcuchowego, a pandy generująSettingWithCopyWarning
tego rodzaju aktualizację indeksowania łańcuchowego.Teraz jest użycie
.copy()
. Aby usunąć ostrzeżenie, zrób kopię, aby wyraźnie wyrazić swój zamiar:Ponieważ modyfikujesz kopię, wiesz, że oryginał
dfc
nigdy się nie zmieni i nie spodziewasz się, że ulegnie zmianie. Twoje oczekiwania pasują do zachowania, a następnieSettingWithCopyWarning
znika.Uwaga: jeśli chcesz zmodyfikować oryginalną ramkę DataFrame, dokument sugeruje użycie
loc
:źródło
Generalnie bezpieczniej jest pracować na kopiach niż na oryginalnych ramkach danych, z wyjątkiem sytuacji, gdy wiesz, że nie będziesz już potrzebować oryginału i chcesz kontynuować pracę z wersją zmanipulowaną. Normalnie nadal można by było wykorzystać oryginalną ramkę danych do porównania z wersją zmanipulowaną, itp. Dlatego większość ludzi pracuje nad kopiami i na końcu łączy je.
źródło
Załóżmy, że masz ramkę danych, jak poniżej
Jeśli chcesz stworzyć inny,
df2
identyczny zdf1
, bezcopy
Chciałbym zmodyfikować wartość df2 tylko jak poniżej
W tym samym czasie zmienia się również df1
Ponieważ dwa df są takie same
object
, możemy to sprawdzić za pomocąid
Czyli jako ten sam obiekt i jedna zmiana na inną, również przekazują tę samą wartość.
Jeśli dodamy
copy
, i terazdf1
idf2
uważamyobject
, że są różne , jeśli dokonamy tej samej zmiany w jednym z nich, drugi się nie zmieni.Warto wspomnieć, że podczas podzbioru oryginalnej ramki danych można bezpiecznie dodać również kopię, aby uniknąć
SettingWithCopyWarning
źródło