python dataframe에 있는 값을로 연산을 하는데
자꾸 아래와 같은 오류가 떠서 신경쓰여서 찾아보았었다.
<ipython-input-434-09caeaeba2c4>: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
이러한 오류가 나는 이유에 대해서 정리해보았다.
1. 오류가 나고 실행이 아예 안되는 경우
Dataframe에서 값을 조건부로 가져다 쓸 경우
그건 dataframe의 한 부분이기때문에,
그 이후에 df에 새로운 컬럼을 만들어 값을 넣어도,
이미 조건부로 필터를 했기에,
Dataframe에 NULL 값이 존재한다.
따라서, Dataframe에서 조건부로 가져올 경우에는
copy()해서 구조도 그대로 가져오는 방법을 사용한다.
(아래 코드 참고)
# with SettingWithCopyWarning
df_positive = df[df.NUM >= 0]
df_positive['SQUARED'] = df_positive.NUM ** 2
# 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: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
# without SettingWithCopyWarning
df_positive = df[df.NUM >= 0].copy()
df_positive['SQUARED'] = df_positive.NUM ** 2
print(df_positive)
# NUM SQUARED
# 2 5 25
# 3 9 81
# 4 7 49
# 7 4 16
# 9 6 36
2. 전체를 다 연산으로 사용하여 결과 값은 나오는데, 에러가 뜨는 경우
내가 이 글을 쓰게 된 주된 이유이기도 하다.
이런 경우에는 dataframe의 부분만 가져온 것이 아니라 그냥 연산만 하는거여서,
실행은 되는데 내가 원하는 값이 제대로 안나와서 뭐가 문제인지 고민하고 있었다.
for i in range(len(df['prediction'])):
df['diff_x'][i] = df['answer_x'][i] - df['prediction_x'][i]
df['diff_y'][i] = df['answer_y'][i] - df['prediction_y'][i]
df['diff_z'][i] = df['answer_z'][i] - df['prediction_z'][i]
##결과
# <ipython-input-434-09caeaeba2c4>: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
# df['diff_x'][i] = df['answer_x'][i] - df['prediction_x'][i]
# <ipython-input-434-09caeaeba2c4>:3: 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
# df['diff_y'][i] = df['answer_y'][i] - df['prediction_y'][i]
# <ipython-input-434-09caeaeba2c4>:4: 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
# df['diff_z'][i] = df['answer_z'][i] - df['prediction_z'][i]
이럴 때는 결과값을 봐보자.
왜 연산이 제대로 안되었는지 확인을 하려면
DataFrame의 각 컬럼의 type을 확인해봐야한다.
df.dtypes 로 확인 가능하다.
나 같은 경우는, float형이 아니라 int형으로 되어 있어서 값이 제대로 출력이 안되었던 것이였다.
따라서 astype을 이용해서 해당 컬럼의 type을 바꿔주었다.
분명 소숫점까지 있는 float형들의 단순연산인데 값이 왜 다 0으로 뜨나 엄청 고민했었다.
이런건 분명 기본적인 부분인데, 아직도 이런 실수를 하는 것을 보면
좀 더 주의깊게 코드를 살펴볼 필요가 있다.
참고로 1번의 문제사항은 해당 error를 구글에 검색하면서 찾은 이유였다.
코드를 잘 짜는 사람들은 최대한 저런 오류가 안뜨도록 주의해서 짠다고한다.
하지만, 나는 그냥 단순 연산인데 왜 저렇게 뜨는 것인지는 아직도 잘 모르겠다....ㅎㅎㅎ
그치만 연산의 문제는 type을 꼭 확인해야한다는 사실을 알게 되었다.
참고 : https://emilkwak.github.io/pandas-dataframe-settingwithcopywarning
'컴퓨터쟁이 > Python' 카테고리의 다른 글
jupyter notebook으로 ipykernel 생성하기 (0) | 2022.04.01 |
---|---|
python pip install requirement.txt 오류나도 끊김없이 설치하기 (0) | 2022.04.01 |
우분투 jupyter notebook 파일 삭제 후 복원하기 (0) | 2022.03.08 |
error: OpenCV(4.5.3) :-1: error: (-5:Bad argument) in function 'circle' (0) | 2022.03.02 |
python 패키징 하는 방법 2 - py2exe (1) | 2021.08.26 |