Основная цель состоит в том, чтобы избежать цепной индексации и устранить SettingWithCopyWarning
.
Здесь цепная индексация что-то вроде dfc['A'][0] = 111
В документе говорится, что при возвращении представления вместо копии следует избегать цепной индексации . Вот немного измененный пример из этого документа:
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
Здесь aColumn
это представление, а не копия исходного DataFrame, поэтому изменение aColumn
также приведет к изменению оригинала dfc
. Далее, если мы сначала проиндексируем строку:
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
На этот раз zero_row
это копия, поэтому оригиналdfc
не изменяется.
Из этих двух примеров выше мы видим неоднозначно, хотите ли вы изменить исходный DataFrame. Это особенно опасно, если вы напишите что-то вроде следующего:
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
На этот раз это не сработало. Здесь мы хотели изменить dfc
, но мы фактически изменили промежуточное значение, dfc.loc[0]
которое является копией и немедленно отбрасывается. Это очень трудно предсказать , будет ли промежуточное значение , как dfc.loc[0]
и dfc['A']
вид или копию, так что это не гарантировано , будет ли или не будет обновляться оригинал DataFrame. Вот почему следует избегать цепной индексации, и pandas генерирует SettingWithCopyWarning
для этого вида обновления цепочечной индексации.
Теперь это использование .copy()
. Чтобы устранить предупреждение, сделайте копию, чтобы явно выразить свое намерение:
In [12]: zero_row_copy = dfc.loc[0].copy()
In [13]: zero_row_copy['A'] = 444 # This time no warning
Поскольку вы dfc
изменяете копию, вы знаете, что оригинал никогда не изменится, и вы не ожидаете, что она изменится. Ваше ожидание соответствует поведению, а затем SettingWithCopyWarning
исчезает.
Примечание. Если вы хотите изменить исходный DataFrame, в документе предлагается использовать loc
:
In [14]: dfc.loc[0,'A'] = 555
In [15]: dfc
Out[15]:
A B
0 555 1
1 bbb 2
2 ccc 3