O objetivo principal é evitar a indexação encadeada e eliminar o SettingWithCopyWarning.
Aqui a indexação encadeada é algo como dfc['A'][0] = 111
O documento dizia que a indexação encadeada deve ser evitada em Retornando uma exibição versus uma cópia . Aqui está um exemplo ligeiramente modificado desse 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
Aqui aColumnestá uma visualização e não uma cópia do DataFrame original; portanto, a modificação também aColumnfará com que o original dfcseja modificado. Em seguida, se indexarmos a linha primeiro:
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
Desta vez zero_rowé uma cópia, portanto o original dfcnão é modificado.
A partir desses dois exemplos acima, vemos que é ambíguo se você deseja ou não alterar o DataFrame original. Isso é especialmente perigoso se você escrever algo como o seguinte:
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
Desta vez, não funcionou. Aqui queríamos mudar dfc, mas na verdade modificamos um valor intermediário dfc.loc[0]que é uma cópia e é descartado imediatamente. É muito difícil prever se o valor intermediário como dfc.loc[0]ou dfc['A']é uma visão ou uma cópia, por isso não é garantido ou não trama de dados original será atualizado. É por isso que a indexação em cadeia deve ser evitada, e o pandas gera o SettingWithCopyWarningpara esse tipo de atualização de indexação em cadeia.
Agora é o uso de .copy(). Para eliminar o aviso, faça uma cópia para expressar sua intenção explicitamente:
In [12]: zero_row_copy = dfc.loc[0].copy()
In [13]: zero_row_copy['A'] = 444 # This time no warning
Como você está modificando uma cópia, sabe que o original dfcnunca será alterado e não espera que seja alterado. Sua expectativa corresponde ao comportamento e depois SettingWithCopyWarningdesaparece.
Nota, se você deseja modificar o DataFrame original, o documento sugere que você use loc:
In [14]: dfc.loc[0,'A'] = 555
In [15]: dfc
Out[15]:
A B
0 555 1
1 bbb 2
2 ccc 3