2 분 소요

※ Chained Assignment와 Hidden Chaining

  • Assignment
    • 특정 셀에 값을 할당하거나 특정 컬럼에 배열을 할당하는 것
    • Setting 또는 Set연산의 의미를 가짐
> df = pd.DataFrame()

# Assignment의 예시
> df['Group'] = ['A', 'A', 'B', 'B', 'C'] # 컬럼에 배열 할당
> df['Value'] = [1, 5, 2, 7, 0] # 컬럼에 배열 할당
> df.loc[0, 'Value'] = 100 # 특정 셀에 값 할당


  • Access
    • 특정 셀, 특정 행, 특정 컬럼에 접근하는 것
    • Getting 또는 Get연산의 의미를 가짐
# Access의 예시
> df[df['Group'] == 'A'] # 특정 행 추출
> df[['Group']] # 특정 컬럼 추출
> df.loc[0, 'Value'] # 특정 셀 추출


■ Chained Assignment

  • 두 개 이상의 연산이 연쇄적으로 연결되어 값을 할당하는 것
    = 특정 조건으로 필터링 함과 동시에 값을 할당하는 것
    = Access와 Assignment가 동시에 발생하는 것
    = Get연산과 Set연산이 동시에 발생하는 것
> df = pd.DataFrame()
> df['Group'] = ['A', 'A', 'B', 'B', 'C']
> df['Value'] = [1, 5, 2, 7, 0]
> df
  Group  Value
0     A      1
1     A      5
2     B      2
3     B      7
4     C      0


# e.g. Chained Assignment
> df[df['Group'] == 'A']['Value'] = 100
# SettingWithCopyWarning 발생
# df의 값이 바뀌지 않음

# 경고를 피하는 올바른 코드
> df.loc[df['Group']=='A', 'Value'] = 100
> df
  Group  Value
0     A    100
1     A    100
2     B      2
3     B      7
4     C      0


# e.g. Chained Assignment
> df.loc[df['Group']=='A', 'Value'][0] = 99
# SettingWithCopyWarning 발생하지는 않으나
# df의 값이 바뀌지 않음

# 올바른 코드
> df.loc[df.index[df['Group']=='A'][0], 'Value']= 99
> df
  Group  Value
0     A     99
1     A    100
2     B      2
3     B      7
4     C      0


■ Hidden Chaining

  • 특정 조건으로 데이터를 필터링한 후, 다른 변수에 선언하여 숨긴 다음에 assignment를 수행하는 것
  • 중간 결과가 변경된 후 최종 결과에 영향을 미치지 않는 경우를 의미. 이로 인해, 의도한 대로 결과가 나오지 않을 수 있음
> df = pd.DataFrame()
> df['Group'] = ['A', 'A', 'B', 'B', 'C']
> df['Value'] = [1, 5, 2, 7, 0]
> df
  Group  Value
0     A      1
1     A      5
2     B      2
3     B      7
4     C      0


# e.g. Hidden Chaining
> temp = df[df['Group'] == 'A'] # 필터링 결과를 새 변수에 할당하여 숨김
> temp
  Group  Value
0     A      1
1     A      5

> temp['VALUE'] = 100
# SettingWithCopyWarning 발생
# get연산과 set연산이 연결되어 있기 때문.
> temp
  Group  Value  VALUE
0     A      1    100
1     A      5    100
# temp의 값은 변경이 되긴 함

# 경고를 피하는 올바른 코드
> temp = df[df['Group'] == 'A'].copy()
> temp['Value'] = 100
> temp
  Group  Value  VALUE
0     A      1    100
1     A      5    100


■ SettingWithCopyWarining

  • 작성자의 의도를 모르거나 결과물 예측이 불가능할 경우
  • Access의 Get연산과 Assignment의 Set연산이 동시에 발생되어, 그 결과가 복사본(copy)인지 원래 데이터의 일부를 나타낸 것(view) 중 어떤 것이 나올지 예측이 불가능함

□ 경고창 끄는 방법

> pd.set_option('mode.chained_assignment', None)

□ 원래대로 돌려놓기

> pd.set_option('mode.chained_assignment', 'warn')

□ 경고가 아니라 에러로 취급하고 싶을때

pd.set_option('mode.chained_assignment', 'raise')



※ View vs. Copy

■ View

  • 원본 데이터의 일부를 참조함.
  • view에서의 변경 사항은 원본 데이터에도 영향을 미침


■ Copy

  • 원본 데이터의 복사본을 만듦
  • 복사본에서의 변경 사항은 원본 데이터에 영향을 미치지 않음

댓글남기기