データの用意
df = pd.DataFrame([[None for j in range(2)] for i in range(3)], columns=['before', 'after'])
df['before'] = df['before'].apply(lambda x:[0,0])
before | after |
---|---|
[0, 0] | None |
[0, 0] | None |
[0, 0] | None |
上記のようなテーブルがあったときに、beforeをafterへコピーしたいと思います。
完成予想図
before | after |
---|---|
[0, 0] | [0, 0] |
[0, 0] | [0, 0] |
[0, 0] | [0, 0] |
OKな例
import copy
df["after"] = df["before"].apply(lambda x:copy.deepcopy(x))
このように一行づつdeepcopyする必要があります。
NGな例
以下、間違えていた方法を挙げます。
浅いコピー
df["after"] = df["before"].copy()
カラムの中身がstrやintであれば実行できますが、listは参照になってしまいます。
カラムをdeepcopy
df["after"] = copy.deepcopy(df["before"])
deepcopyしているので実行できそうですが、こちらもダメです。
確認する
# カラムの識別値
print(id(df["before"])) # >>> 140355706322576
print(id(df["after"])) # >>> 140355202828368
# リストの識別値
print(id(df["before"][0])) # >>> 140355188788272
print(id(df["after"][0])) # >>> 140355188788272
id関数を使用するとオブジェクトの識別値を確認することができます。
カラムは識別値が違うため異なるオブジェクトとして存在していますが、リストは値が同じで参照していることがわかります。
そのためafterの中身を変更しようとするとbeforeまで変わってしまいます。
なのでOK例のように1行づつdeepcopyするのが良さそうです。
参考文献