【Python】Pandasで発生する警告「SettingWithCopyWarning」の解決策

【Python】Pandasで発生する警告「SettingWithCopyWarning」の解決策

この記事ではSettingWithCopyWarningの解決と原因を紹介します。

この記事での目標
・SettingWithCopyWarningの解決
・SettingWithCopyWarningの原因理解

 

DataFrameとSeries型の違いがわからない人はまず以下の記事で理解しましょう!!
DataFrameとSeriesの違いを紹介
その他Pythonの記事は以下にまとめています!!

Python記事まとめ

 

DataFrameを色々いじって実行すると警告で「SettingWithCopyWarning」が出ることがあります。
例えば以下のような動作をすると出ます。

警告内容としては元データが変更されているけどいいの??って感じのことを言ってます。
よくわからないかもしれませんが、原因を知れば納得するはずです。
とはいえまずはすっきりしたいと思うので解決策を紹介します。

[スポンサーリンク]


SettingWithCopyWarningの解決策

解決策を端的に言うとDataFrameをコピーする時にcopy()を使ってないからです。
先ほどの例でDataFrameをコピーしている部分にcopy()を付けて実行してみます。

copy()を付けることで警告がでなくなりました。
ひとまずこれで解決です。

 

SettingWithCopyWarningの原因

SettingWithCopyWarningが発生する原因は=を使ってもコピーできておらず参照渡しになっているためです。
以下のような値がすべて1のDataFrameであるdfが存在しているとしましょう。

dfをコピーしたdf_cの0列目に100を足してみます。

はい、きちんとdf_cの0列目に100が足されていました。
ここまではいいですね!

しかしここでdfを見てみると…

なんとdfにも100が足されています!!
処理の流れを見てもdf自体に100を足していません。
足したのはdf_cですが、なぜかdfにも100が足されてしまいました。

この理由は参照渡しだからです。
最初の「df_c=df」を見るとこうなってるように見えるけど…

実はこうなっているんです。

つまりdf_cはただdfのアドレスを持っているだけでdf_cが表示する値はあくまでそのアドレスにあるdfの値なのです。
そのためdf_cを編集するということはdfも編集されてしまうことになるのです。
つまり=じゃコピーできてないよということ。

なので「SettingWithCopyWarning」は元のDataFrameが変わってるけどいいの??ということを言ってくれてたんですね。

ではコピーするにはどうすればいいのか?というと冒頭の解決策で紹介したcopyメソッドを使用することです。
コピーしたいDataFrame.copy()を付けましょう。

この通り、df_cは+100されており、dfは+100されませんでした。

今回、DataFrameで確認しましたが、Series型も参照渡しがデフォルトになっているのでコピーしたい時はcopyメソッドを使用しましょう。

リストも参照渡しになっている

ちなみにリストもデフォルトが参照渡しになっています。
確認するために値が1しかないlist1list2に参照渡しして、list2を-100します。

はい、予想通りlist1list2が同じ値になってしまいました。

これを防ぐためにリストでもcopyメソッドを使用することで解決します。

copy()を付けることでlist1が編集されなくなりました。

まとめ

PandasDataFrameSeriesリストコピーする時は=ではなくcopyメソッドを使いましょう。
警告が出ていなくとも思わぬバグを防ぐことができます。

そもそもなぜ参照渡しがデフォルトかというと
リストDataFrameなどは容量が大きくなりがちなので値渡しだとメモリを圧迫してしまうからです。
値渡しは重たいけど参照渡しならアドレスだけだからめっちゃ軽いというわけ

ということでバグ防止のためにもコピーする時はcopy()をつけ忘れないように気を付けましょう!

[スポンサーリンク]


Pandasカテゴリの最新記事