Lo scopo principale è evitare l'indicizzazione concatenata ed eliminare il file SettingWithCopyWarning
.
Qui l'indicizzazione concatenata è qualcosa di simile dfc['A'][0] = 111
Il documento afferma che l'indicizzazione concatenata dovrebbe essere evitata in Restituzione di una vista rispetto a una copia . Ecco un esempio leggermente modificato da quel documento:
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
Qui aColumn
è una vista e non una copia del DataFrame originale, quindi la modifica aColumn
comporterà anche la dfc
modifica dell'originale . Quindi, se prima indicizziamo la riga:
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
Questa volta zero_row
è una copia, quindi l'originale dfc
non viene modificato.
Da questi due esempi precedenti, vediamo ambiguo se si desidera modificare il DataFrame originale. Ciò è particolarmente pericoloso se scrivi qualcosa di simile al seguente:
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
Questa volta non ha funzionato affatto. Qui volevamo cambiaredfc
, ma in realtà abbiamo modificato un valore intermedio dfc.loc[0]
che è una copia e viene immediatamente scartato. È molto difficile prevedere se il valore intermedio gradisce dfc.loc[0]
o dfc['A']
è una vista o una copia, quindi non è garantito se DataFrame originale verrà aggiornato. Ecco perché è necessario evitare l'indicizzazione concatenata e Panda genera SettingWithCopyWarning
questo tipo di aggiornamento dell'indicizzazione concatenata.
Ora è l'uso di .copy()
. Per eliminare l'avviso, creane una copia per esprimere esplicitamente la tua intenzione:
In [12]: zero_row_copy = dfc.loc[0].copy()
In [13]: zero_row_copy['A'] = 444 # This time no warning
Poiché stai modificando una copia, sai che l'originale dfc
non cambierà mai e non ti aspetti che cambi. Le tue aspettative corrispondono al comportamento, quindi SettingWithCopyWarning
scompare.
Nota, se si desidera modificare il DataFrame originale, il documento suggerisce di utilizzare loc
:
In [14]: dfc.loc[0,'A'] = 555
In [15]: dfc
Out[15]:
A B
0 555 1
1 bbb 2
2 ccc 3