エラーTweetpandasで頻出の警告にSettingWithCopyWarningがある。エラーではなく警告なので処理が止まることはないが、放っておくと気づかないうちに予期せぬ結果になってしまう場合がある。documentationここでは以下の内容について説明する。copy()でコピーを生成loc[]やiloc[]、コピーやビューなどについての詳細は以下の記事を参照。以下の内容のpandasのバージョン0.25.1。バージョンが異なると挙動が異なる場合があるので注意。おすすめしないが、警告はPythonの標準ライブラリwarningsモジュールで非表示にすることもできる。assignment。indexingと呼ぶ。assignmentと呼び、この際にSettingWithCopyWarningが発生する場合がある。DataFrame.という文言の通り、DataFrameのスライスのコピーに対して値を代入しようとしていますよ、という警告。最初のインデクシング[]がビューを返す場合は問題ないが、コピーを返す場合、コピーに対して二つ目のインデクシング[]が適用されて値が代入されるので、元のDataFrameの値は変わらない(代入されない)ということが起こってしまう。この例の場合、最初のloc['x':'y']が返すのはコピーではなくビューなので問題なく値が代入されている。[]がコピーを返すかビューを返すかは判定できないので、SettingWithCopyWarningが発生したからといって必ずしもコピーが生成されているとは限らない。次のような場合もある。'y']]が返すのはコピーなので、さらにインデクシングを適用して値を代入しても元のDataFrameの値は変わらない。これは意図した結果ではない。ややこしいことに、この場合はSettingWithCopyWarningが発生しない。少なくともバージョン0.25.1の時点では、SettingWithCopyWarningが発生したからといって問題があるとは限らないし、SettingWithCopyWarningが発生しなかったからといって問題がないとは限らない。indexingを避ける必要がある。indexingを防ぐには、警告メッセージにもあるようにインデクシングを連鎖させずに1つににまとめればよい。instead上の2つの例は以下のように書ける。pandas_setting_with_copy_warning.py単独のインデクシングであれば元のDataFrameに値が代入されることが保証されている。処理速度もこちらのほうが速い。行名・列名(行ラベル・列ラベル)と行番号・列番号を組み合わせて範囲を指定したい場合はインデクシングを繰り返したくなる。locは行名・列名、ilocは行番号・列番号で指定する必要があるので、行番号と列ラベルのように混在して指定することができない。pandas_setting_with_copy_warning.pyこのような場合はindex属性およびcolumns属性を使って、行番号・列番号から行名・列名を取得する。pandas_setting_with_copy_warning.pyコードは長くなるが、行名・列名に統一して指定することができる。ilocではstopが結果に含まれるが、行名・列名のlocではstopが結果に含まれない。columns属性で行番号・列番号から行名・列名を取得する際に-1する必要がある。assignment問題の内容1つ目のインデクシングをオブジェクトに代入した場合も同様。連鎖していないように見えるが、以下の例はdf.loc['x':'y']['a']と同じ。値を代入するとSettingWithCopyWarningが発生する。'y']]['a']と同じ。'y']]でコピーが生成されるので元のDataFrameの値は更新されない。pandas_setting_with_copy_warning.py以下のようなことも起こる。スライスで取得したオブジェクトに列を追加する例。pandas_setting_with_copy_warning.py元のDataFrameに存在しない列を追加したにもかかわらず、一部ではメモリを共有しているというよくわからない状態になっている。[]といったインデクシングでビューが生成されるかコピーが生成されるかは判定できず、必ずビューを生成することもできない。書き捨てのコードであったり、インデクシングで選択したあとで元のDataFrameを使うことがない(値が変わっても変わらなくても問題ない)のであれば神経質にならなくてもいいが、様々なデータを対象とする可能性があるコードの中でビューが返されることを前提とするのは危険。唯一できる対処法はcopy()でコピーを生成すること。インデクシングでオブジェクトを生成する場合は常にコピーとして扱う。pandas_setting_with_copy_warning.pyなお、インデクシングでコピーが返される場合にさらにcopy()を実行すると一時的にメモリが余分に確保されてしまう可能性がある。巨大なデータを扱う場合は要注意。データの内容や処理が限定されている状況でいくつかのパターンであらかじめコピーが生成されることを確認した上であれば、copy()を使わないという選択肢もあるかもしれない。