HOWTO · Pandas

Pandas DataFrame をコピーする

このチュートリアルでは、DataFrame.copy()メソッドを使用して DataFrame オブジェクトのコピーを作成する方法を紹介し、DataFrame.copy()メソッドの使用方法を探ります。

このページの内容

pandas の DataFrame をコピーするには、DataFrame.copy() を呼び出します。デフォルトの deep=True では別の DataFrame が作成されるため、コピー先のセルを変更しても元のセルは変わりません。データを独立して編集したい場合に使います。

DataFrame.copy() の構文とコピーの深さ

このメソッドは deep 引数を受け取ります。構文は df.copy(deep=True) です。デフォルトは True なので、df.copy() も同じ意味です。deep=True を指定すると、pandas は DataFrame のデータとインデックスをコピーします。これは pandas のデータ構造に対する deep コピーですが、object dtype のセルに格納された Python オブジェクトを再帰的にコピーするわけではありません。たとえば、セルに変更可能なリストが入っている場合、コピー先の DataFrame にも同じリストへの参照が残ることがあります。入れ子になったオブジェクトも独立させる必要があるなら、そのオブジェクトを別途コピーしてください。

deep=False の場合、pandas は最初にデータとインデックスをコピーせず、元のものと共有します。その後、どちらかの DataFrame を通じて代入したときの動作は、pandas のバージョンと Copy-on-Write が有効かどうかによって異なります。浅いコピーによる編集が元に伝わる、またはどの環境でも確実に分離されるとは考えないでください。独立性が重要なら、デフォルトの deep コピーを使います。データの共有を意図している場合は、アプリケーションで使う pandas のバージョンと Copy-on-Write モードについて、仕様を確認してください。

独立した DataFrame のコピーを作成する

次の例を実行します。

このセクションのコードと表示されるラベルや出力は英語のままです。

import pandas as pd

original = pd.DataFrame({"score": [10]})
independent = original.copy()
independent.loc[0, "score"] = 99
print(f"original={original.loc[0, 'score']}, copy={independent.loc[0, 'score']}")
original=10, copy=99

この代入ではコピー先の DataFrame のセルが変更されますが、original の値は 10 のままです。この例ではデフォルトの deep=True を使っています。original.copy(deep=True) と書けば、その選択を明示できます。変更するセルを指定するには .loc[row, column] を使います。元のデータと比較したり、再利用したりする必要がある場合は、元の変数も残しておきましょう。

deep=False と共有データを理解する

浅いコピーは、データをすぐに複製せずに新しい DataFrame オブジェクトを作りたい場合に役立ちます。ただし、その後の変更がどう反映されるかを一律に保証するものではありません。書き込みが分離されるか、別のオブジェクトからも見えるかは、pandas のバージョンと Copy-on-Write の動作に左右されます。deep=False はバージョンによって変更時の動作が異なる選択肢であり、両方の DataFrame を確実に同時編集する方法ではありません。予測可能な独立編集には deep=True を選びます。特定のアプリケーションでの動作を把握するには、その pandas のバージョンと Copy-on-Write の設定を確認してください。

deep 引数を指定しても、入れ子になったオブジェクトが独立するわけではありません。たとえば、object dtype のセルにリストが入っている場合、DataFrame のコピーによって pandas のコンテナは複製されても、各リストが再帰的に複製されるわけではありません。そのため、セル内のリストを変更すると、両方の DataFrame から参照できるオブジェクトに影響することがあります。この違いが重要な場合は、入れ子になった変更可能な値を別途処理してください。

DataFrame または列を変数に代入する

other = original のような代入は、同じ DataFrame オブジェクトを別の変数名に結び付けます。DataFrame.copy() を呼び出すことも、独立したデータを作成することもありません。どちらの名前を通じて変更しても、同じオブジェクトに作用します。

同様に、scores = original["score"] は列を pandas の Series として選択するもので、独立したコピーを明示的に要求する操作ではありません。独立性が必要な場合、変数への代入や列の選択をコピーの代わりに使わないでください。DataFrame の場合は other = original.copy()、独立した Series の場合は scores = original["score"].copy() を使います。こうすれば意図が明確になり、偶発的なビューや変更時の動作に頼らずに済みます。まず必要なオブジェクトを選びます。表形式の操作には DataFrame、1列だけ扱うには Series を使い、別々に編集できる結果が必要なときに .copy() を呼び出してください。