98
57

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

pandasで=でコピーした場合とcopy()を使った場合の挙動の違い

Last updated at Posted at 2018-12-04

pythonのpandasにおいては、dataframeのコピーを=で行うと、データのコピーではなく、いわゆる参照渡しになる。
そうすると、下記のように、コピー先の変数に対して操作を行った結果が、コピー元の変数に対して反映される。

import pandas as pd
import numpy as np

## それぞれのやり方でコピーした場合のID
df = pd.DataFrame({ 'A' : 'FOO',
                    'B' : 'foo',
                    'C' : 'ふー'}, index=[1,2,3])

# 確認(Before)
display(df)

# コピー(参照渡し)
df_copy = df
# コピーに対して、1を代入したD列を追加する
df_copy['D'] = 1

# 確認(After)
display(df) 
A B C
1 FOO foo ふー
2 FOO foo ふー
3 FOO foo ふー
A B C D
1 FOO foo ふー 1
2 FOO foo ふー 1
3 FOO foo ふー 1

そのため、基本オブジェクトをコピーしたいときは、copy()を使うようにする。
また、copy()の場合でも、deep=Falseをした場合、参照渡しとなる、といくつかの記事に書いてある。

ただ、それぞれのやり方でコピーした場合のIDを見ると、下記のよう、=を使った場合のみ、idが一致しているので、
=とcopy(deep=False) では挙動が異なるのではと思い確認してみた。

import pandas as pd
import numpy as np

df = pd.DataFrame({ 'A' : 'FOO',
                    'B' : 'foo',
                    'C' : 'ふー'}, index=[1,2,3])
equal = df
deep = df.copy() # defaultはtrue
shallow = df.copy(deep=False) 

print('id(df):',id(df))
print('id(equal):',id(equal))
print('id(deep):',id(deep))
print('id(shallw):',id(shallow))
id(df): 4569239336
id(equal): 4569239336
id(deep): 4569145072
id(shallw): 4569180200

結論

=を使った場合は、値の更新だろうと追加だろうと全てリンクするが、copy(deep=False) の場合は値の更新のみリンクする。
※当然、copy(deep=True)の場合は全く異なるオブジェクトなので、更新も追加もリンクしない

  1. [追加を行った場合] ▶ equalのみ追加される
  2. [値の変更(行)の変更を行った場合] ▶ equal, shallowの変更が適用される
  3. [値の変更(列)の変更を行った場合] ▶ equal, shallowの変更が適用される
  4. [列の追加&変更を行った場合]  ▶ equalは変更もできるが、shallowは値の変更はできなくなる

追加を行った場合


df = pd.DataFrame({ 'A' : 'FOO',
                    'B' : 'foo',
                    'C' : 'ふー'}, index=[1,2,3])

print('----Before----')

# 確認(Before)
display(df)

# dfを元にコピー
equal = df 
deep = df.copy() # defaultはtrue
shallow = df.copy(deep=False) 

# コピー先を操作
equal['D'] = 'equal'
deep['E'] = 'deep'
shallow['F'] = 'shallow'

print('----After----')

# 確認(After)
display(df) # equalのみ追加される

----Before----

A B C
1 FOO foo ふー
2 FOO foo ふー
3 FOO foo ふー

----After----

A B C D
1 FOO foo ふー equal
2 FOO foo ふー equal
3 FOO foo ふー equal

値の変更(行)の変更を行った場合


df = pd.DataFrame({ 'A' : 'FOO',
                    'B' : 'foo',
                    'C' : 'ふー'}, index=[1,2,3])

print('----Before----')

# 確認(Before)
display(df)

# dfを元にコピー
equal = df 
deep = df.copy() # defaultはtrue
shallow = df.copy(deep=False) 

# コピー先を操作
equal.iloc[0,:] = 'equal'
deep.iloc[1,:] = 'deep'
shallow.iloc[2,:] = 'shallow'

print('----After----')

# 確認(After)
display(df) # equal, shallowの変更が適用される

----Before----

A B C
1 FOO foo ふー
2 FOO foo ふー
3 FOO foo ふー

----After----

A B C
1 equal equal equal
2 FOO foo ふー
3 shallow shallow shallow

値の変更(列)の変更を行った場合


df = pd.DataFrame({ 'A' : 'FOO',
                    'B' : 'foo',
                    'C' : 'ふー'}, index=[1,2,3])

print('----Before----')

# 確認(Before)
display(df)

# dfを元にコピー
equal = df 
deep = df.copy() # defaultはtrue
shallow = df.copy(deep=False) 

# コピー先を操作
equal.iloc[:,0] = 'equal'
deep.iloc[:,1] = 'deep'
shallow.iloc[:,2] = 'shallow'

print('----After----')

# 確認(After)
display(df) # equal, shallowの変更が適用される

----Before----

A B C
1 FOO foo ふー
2 FOO foo ふー
3 FOO foo ふー

----After----

A B C
1 equal foo shallow
2 equal foo shallow
3 equal foo shallow

列の追加&変更を行った場合


df = pd.DataFrame({ 'A' : 'FOO',
                    'B' : 'foo',
                    'C' : 'ふー'}, index=[1,2,3])

print('----Before----')

# 確認(Before)
display(df)

# dfを元にコピー
equal = df 
deep = df.copy() # defaultはtrue
shallow = df.copy(deep=False) 

# コピー先を操作
equal['D'] = 'add_df' # 参照元に追加
equal['E'] = 'add_equal' # 参照先に追加
equal.iloc[0,:] = 'equal'# 追加後に値の変更
deep.iloc[1,:] = 'deep' # 追加後に値の変更
shallow.iloc[2,:] = 'shallow' # 追加後に値の変更

print('----After----')

# 確認(After)
display(df) # equalは変更もできるが、shallowは値の変更はできなくなる

----Before----

A B C
1 FOO foo ふー
2 FOO foo ふー
3 FOO foo ふー

----After----

A B C D E
1 equal equal equal equal equal
2 FOO foo ふー add_df add_equal
3 FOO foo ふー add_df add_equal
98
57
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
98
57

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?