SettingWithCopyWarning(連鎖代入)

投稿者: | 2022-06-01

参考HP:https://linus-mk.hatenablog.com/entry/2019/02/02/200000

  • SettingWithCopyWarning は警告であり、エラーではない。ただし、その処理が自分の期待どおりに機能しなかった可能性があることを示している
  • VIEW(ビュー、参照)とCOPYの違いを理解しておく

目次

キーワード

代入

  • Assignment、set とも呼ぶ
  • 値を設定する操作
  • 例)data = 5

アクセス

  • Access、get とも呼ぶ
  • 値を返す操作

インデックス

  • indexing
  • データのサブセットを参照する代入またはアクセスのメソッド
  • 例)data[1:5]

連鎖

  • 複数のインデックス操作を連続して使用すること
  • 例)data[1:5][1:3]

連鎖代入

  • 連鎖と代入の組み合わせ。pandasはこれを検出すると警告を出す
  • 「dfのスライスのコピーに値を代入しようとしてます」の意
  • つまり、「スライス元のdf」「スライス先のdf2」どっちに代入しているの?意図によっては期待する結果はでませんよ、的な警告。

対策

明示的にコピーを取る

df = pd.DataFrame(np.arange(15).reshape(5,3), columns=['a','b','c'])
df
    a   b   c
0   0   1   2
1   3   4   5
2   6   7   8
3   9  10  11
4  12  13  14

# dfの列a、cを取得する
df2 = df[['a', 'c']]  # <- df2はdf1のVIEW(参照)になっている
df2

    a   c
0   0   2
1   3   5
2   6   8
3   9  11
4  12  14

# VIEWに代入すると「SettingWithCopyWarning」エラーとなる
df2.iloc[0,0] = 100

# SettingWithCopyWarning: 
# A value is trying to be set on a copy of a slice from a DataFrame
# See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
# iloc._setitem_with_indexer(indexer, value, self.name)

# ここではdf2はdf1とは別物として使いたい(仮定)ため
# エラーを防止するにはCOPYであることをpandasに明示すればよい

df2 = df[['a', 'c']].copy()
df2.iloc[0,0] = 100         # <-エラーなし
df2
     a   c
0  100   2
1    3   5
2    6   8
3    9  11
4   12  14