Series、DataFrame生成時の copy パラメータについて( Pandas 2.2 )
以下の情報は、https://pandas.pydata.org/ を参考にさせていただきました。
自身のメモとして記録しているので、誤った解釈になっているかも知れません。ご注意ください。
Series
copyパラメータ デフォルト False
シリーズまたは 1 次元 ndarray 入力にのみ影響
(デフォルトでコピーされない)
よって、上記以外のリストは、コピーされる(確認済)
DataFrame
copyパラメータ bool または None、デフォルト None
入力データによって、動作が異なる
・辞書データの場合 --> copy=True
(copy=Falseとしても、コピーされているようだ)
・DataFrame または 2d ndarray の場合 --> copy=False
DataFrameのデータを変更する方法によって動作が異なる
s_b[0]=50 や s_b[0]=[50,100] では、
元データとは独立している(変更されない)
s_b.iloc[0,0] = 10 では、元データが変更される
(.locを利用時を含む)
・1 つ以上の Series を含む辞書である場合 --> copy=False
・それ以外は不明(None)だが、下記のものは copy=True のように
動作することを確認済
2次元のリスト
(copy=Falseとしても、コピーされているようだ)
まとめ
Series、DataFrameを生成するときは、メモリを圧迫しないのであれば、copy=True で使用することが安心。
・元データが ndarray、Series であることはよくある。
・元データを変更したくないときは、特に注意深く記述すること。
・元データに変更を加えるときは、
処理結果を明示的に書き換える処理を追加する。
DataFrameからデータを抽出したときは、コピーなのかビューなのかは未確認である。
・抽出や結合などを行った返り値が、コピーなのかビューなのかは
常に意識する。
・普通に扱うデータ量では、copy()メソッドがある場合は利用する。
・メモリ容量を気にする必要がある場合は、コピーなのかビューなのか
を確認し、注意深くスクリプトを記述する。
# 以下、動作確認
import numpy as np
import pandas as pd
# Series(ndarray)
a=np.array([0,1,2])
s = pd.Series(a) # defult: copy=False
a[2]=1000 # 元データを変更 Seriesも変更される
s[0] = 10 # Seriesを変更 ndarrayも変更される
display(a,s)
'''
array([ 10, 1, 1000])
0 10
1 1
2 1000
dtype: int64
'''
# Series(list)
a=[0,1,2]
s = pd.Series(a) # defult: copy=False
a[2]=1000 # 元データを変更 Seriesは変更されない
s[0] = 10 # Seriesを変更 元データは変更されない
display(a,s)
'''
[0, 1, 1000]
0 10
1 1
2 2
dtype: int64
'''
# DataFrame(dictionary)
a = {'c0': [0, 1, 3], 'c1': [2, 4, 6]}
df = pd.DataFrame(a,copy=False) # 辞書は、copy=Falseを指定してもコピーされているようだ
a['c0'][1]=100
df.loc[0,'c0']=50
display(a,df)
'''
{'c0': [0, 100, 3], 'c1': [2, 4, 6]}
c0 c1
0 50 2
1 1 4
2 3 6
'''
# DataFrame(ndarray)
a = np.array([[0, 1, 3],[2, 4, 6]])
df = pd.DataFrame(a) # copy=True
a[0][1]=100 # DataFrameが変更される
df.iloc[0,0]=50 # ndarrayが変更される
df[2]=[1000,2000] # ndarrayは変更されない
display(a,df)
'''
array([[ 50, 100, 3],
[ 2, 4, 6]])
0 1 2
0 50 100 1000
1 2 4 2000
'''
# DataFrame(list)
a = [[0, 1, 3],[2, 4, 6]]
df = pd.DataFrame(a,copy=False) # リストは、copy=Falseを指定してもコピーされているようだ
a[0][1]=100 # DataFrameは変更されない
df.iloc[0,0]=50 # listは変更されない
df[2]=[1000,2000] # listは変更されない
display(a,df)
'''
[[0, 100, 3], [2, 4, 6]]
0 1 2
0 50 1 1000
1 2 4 2000
'''