05 January 2021

copy에 대해

import pandas as pd
# 데이터프레임에 a 라는 컬럼을 생성합니다.
df = pd.DataFrame({"a": range(5)})
df
a
0 0
1 1
2 2
3 3
4 4
# 0, 1번 인덱스값만 추출해서 df2 에 사본을 만듭니다.

df2 = df.loc[0:1]
df2
a
0 0
1 1
# df, df2는 다른 id값을 갖고 있습니다.
print(id(df))
print(id(df2))
140586104665360
140586087374288
df2
a
0 0
1 1
# df2의 a컬럼의 값을 [4, 5] 로 변경합니다.
# 데이터 프레임의 일부의 사본을 생성해 올 때 copy()를 사용하지 않고 
# 사본을 생성하게 되면 아래와 같은 경고메시지가 발생합니다.
df2["a"] = [4, 5]
df2
/Users//opt/anaconda3/lib/python3.7/site-packages/ipykernel_launcher.py:4: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  after removing the cwd from sys.path.
a
0 4
1 5
# 0 번 인덱스의 a 컬럼에 다른 값을 넣으려고 할때도 아래의 경고 메시지가 출력됩니다.
df2.loc[0, "a"] = 7
df2
/Users//opt/anaconda3/lib/python3.7/site-packages/pandas/core/indexing.py:671: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  self._setitem_with_indexer(indexer, value)
/Users//opt/anaconda3/lib/python3.7/site-packages/ipykernel_launcher.py:2: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
a
0 7
1 5
# 그리고 df2의 값을 변경해 주었는데 df의 0,1 번 인덱스 값이 변경된 것을 확인할 수 있습니다.
df
a
0 7
1 5
2 2
3 3
4 4
# 그럼 이번에는 copy()를 통해 df2를 df3에 사본을 생성합니다.
# pandas copy의 기본값은 df.copy(deep: bool = True) 깊은복사 입니다.
df3 = df[:3].copy()
df3
a
0 7
1 5
2 2
# df, df2, df3는 모두 다른 id값을 가집니다.
print(id(df))
print(id(df2))
print(id(df3))
140586104665360
140586087374288
140586104960528
# df3의 a컬럼의 값을 변경합니다.
df3["a"] = [-2, -3, -4]
df3
a
0 -2
1 -3
2 -4
# df3의 값을 변경해도 원본 df의 값은 마지막 상태를 유지하고 있습니다.
# df3의 변경값이 df에 반영되지 않았습니다.
df
a
0 7
1 5
2 2
3 3
4 4
# .copy()를 통해 깊은 복사를 해주게 되면 사본이 원본을 바라보지 않습니다.
# 따라서 사본을 생성할 때 .copy()를 사용하면 원본값에 영향을 주지 않게 되고 
# 값을 변경할 때도 경고메시지가 출력되지 않습니다.