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:
In [1]: import pandas as pd
In [2]: dfc = pd.DataFrame({'A':['aaa','bbb','ccc'],'B':[1,2,3]})
In [3]: dfc
Out[3]:
A B
0 aaa 1
1 bbb 2
2 ccc 3
In [4]: aColumn = dfc['A']
In [5]: aColumn[0] = 111
SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame
In [6]: dfc
Out[6]:
A B
0 111 1
1 bbb 2
2 ccc 3
Tutaj aColumn
jest to widok, a nie kopia z oryginalnej ramki DataFrame, więc modyfikacja aColumn
spowoduje również dfc
zmodyfikowanie oryginału . Następnie, jeśli najpierw zindeksujemy wiersz:
In [7]: zero_row = dfc.loc[0]
In [8]: zero_row['A'] = 222
SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame
In [9]: dfc
Out[9]:
A B
0 111 1
1 bbb 2
2 ccc 3
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:
In [10]: dfc.loc[0]['A'] = 333
SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame
In [11]: dfc
Out[11]:
A B
0 111 1
1 bbb 2
2 ccc 3
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:
In [12]: zero_row_copy = dfc.loc[0].copy()
In [13]: zero_row_copy['A'] = 444 # This time no warning
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ępnie SettingWithCopyWarning
znika.
Uwaga: jeśli chcesz zmodyfikować oryginalną ramkę DataFrame, dokument sugeruje użycie loc
:
In [14]: dfc.loc[0,'A'] = 555
In [15]: dfc
Out[15]:
A B
0 555 1
1 bbb 2
2 ccc 3