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
'''

いいなと思ったら応援しよう!