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



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


```python
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
# コピーに対して、１を代入したD列を追加する
df_copy['D'] = 1

# 確認(After）
display(df) 
```


<div>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>A</th>
      <th>B</th>
      <th>C</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>1</th>
      <td>FOO</td>
      <td>foo</td>
      <td>ふー</td>
    </tr>
    <tr>
      <th>2</th>
      <td>FOO</td>
      <td>foo</td>
      <td>ふー</td>
    </tr>
    <tr>
      <th>3</th>
      <td>FOO</td>
      <td>foo</td>
      <td>ふー</td>
    </tr>
  </tbody>
</table>
</div>



<div>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>A</th>
      <th>B</th>
      <th>C</th>
      <th>D</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>1</th>
      <td>FOO</td>
      <td>foo</td>
      <td>ふー</td>
      <td>1</td>
    </tr>
    <tr>
      <th>2</th>
      <td>FOO</td>
      <td>foo</td>
      <td>ふー</td>
      <td>1</td>
    </tr>
    <tr>
      <th>3</th>
      <td>FOO</td>
      <td>foo</td>
      <td>ふー</td>
      <td>1</td>
    </tr>
  </tbody>
</table>
</div>


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

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


```python
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は値の変更はできなくなる




## 追加を行った場合 

```python

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



<div>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>A</th>
      <th>B</th>
      <th>C</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>1</th>
      <td>FOO</td>
      <td>foo</td>
      <td>ふー</td>
    </tr>
    <tr>
      <th>2</th>
      <td>FOO</td>
      <td>foo</td>
      <td>ふー</td>
    </tr>
    <tr>
      <th>3</th>
      <td>FOO</td>
      <td>foo</td>
      <td>ふー</td>
    </tr>
  </tbody>
</table>
</div>


----After----



<div>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>A</th>
      <th>B</th>
      <th>C</th>
      <th>D</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>1</th>
      <td>FOO</td>
      <td>foo</td>
      <td>ふー</td>
      <td>equal</td>
    </tr>
    <tr>
      <th>2</th>
      <td>FOO</td>
      <td>foo</td>
      <td>ふー</td>
      <td>equal</td>
    </tr>
    <tr>
      <th>3</th>
      <td>FOO</td>
      <td>foo</td>
      <td>ふー</td>
      <td>equal</td>
    </tr>
  </tbody>
</table>
</div>


## 値の変更（行）の変更を行った場合 


```python

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



<div>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>A</th>
      <th>B</th>
      <th>C</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>1</th>
      <td>FOO</td>
      <td>foo</td>
      <td>ふー</td>
    </tr>
    <tr>
      <th>2</th>
      <td>FOO</td>
      <td>foo</td>
      <td>ふー</td>
    </tr>
    <tr>
      <th>3</th>
      <td>FOO</td>
      <td>foo</td>
      <td>ふー</td>
    </tr>
  </tbody>
</table>
</div>


----After----



<div>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>A</th>
      <th>B</th>
      <th>C</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>1</th>
      <td>equal</td>
      <td>equal</td>
      <td>equal</td>
    </tr>
    <tr>
      <th>2</th>
      <td>FOO</td>
      <td>foo</td>
      <td>ふー</td>
    </tr>
    <tr>
      <th>3</th>
      <td>shallow</td>
      <td>shallow</td>
      <td>shallow</td>
    </tr>
  </tbody>
</table>
</div>


## 値の変更（列）の変更を行った場合 


```python

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



<div>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>A</th>
      <th>B</th>
      <th>C</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>1</th>
      <td>FOO</td>
      <td>foo</td>
      <td>ふー</td>
    </tr>
    <tr>
      <th>2</th>
      <td>FOO</td>
      <td>foo</td>
      <td>ふー</td>
    </tr>
    <tr>
      <th>3</th>
      <td>FOO</td>
      <td>foo</td>
      <td>ふー</td>
    </tr>
  </tbody>
</table>
</div>


----After----



<div>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>A</th>
      <th>B</th>
      <th>C</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>1</th>
      <td>equal</td>
      <td>foo</td>
      <td>shallow</td>
    </tr>
    <tr>
      <th>2</th>
      <td>equal</td>
      <td>foo</td>
      <td>shallow</td>
    </tr>
    <tr>
      <th>3</th>
      <td>equal</td>
      <td>foo</td>
      <td>shallow</td>
    </tr>
  </tbody>
</table>
</div>


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


```python

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



<div>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>A</th>
      <th>B</th>
      <th>C</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>1</th>
      <td>FOO</td>
      <td>foo</td>
      <td>ふー</td>
    </tr>
    <tr>
      <th>2</th>
      <td>FOO</td>
      <td>foo</td>
      <td>ふー</td>
    </tr>
    <tr>
      <th>3</th>
      <td>FOO</td>
      <td>foo</td>
      <td>ふー</td>
    </tr>
  </tbody>
</table>
</div>


----After----



<div>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>A</th>
      <th>B</th>
      <th>C</th>
      <th>D</th>
      <th>E</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>1</th>
      <td>equal</td>
      <td>equal</td>
      <td>equal</td>
      <td>equal</td>
      <td>equal</td>
    </tr>
    <tr>
      <th>2</th>
      <td>FOO</td>
      <td>foo</td>
      <td>ふー</td>
      <td>add_df</td>
      <td>add_equal</td>
    </tr>
    <tr>
      <th>3</th>
      <td>FOO</td>
      <td>foo</td>
      <td>ふー</td>
      <td>add_df</td>
      <td>add_equal</td>
    </tr>
  </tbody>
</table>
</div>