Python/Python Pandas

Python Pandas : SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame.

CosmosProject 2024. 7. 4. 19:13
728x90
반응형

 

 

 

DataFrame에 있는 특징 한 가지를 알아보겠습니다.

 

import pandas as pd

dict_test = {
    'col1': [1, 2, 3, 4, 5],
    'col2': [2, 3, 4, 5, 6],
}
df_test = pd.DataFrame(dict_test)


df_test_1 = df_test

df_test_1.loc[:, 'col3'] = 3

 

df_test를 생성하고 df_test_1 = df_test 처럼 df_test_1에 df_test를 할당하였습니다.

 

- df_test_1.loc[:, 'col3'] = 3

그리고 df_test_1에 col3를 추가하였습니다.

 

그러면 df_test_1에만 col3가 생길까요?

아니면 df_test에도 col3가 생길까요?

 

정답은 df_test에도 col3가 생깁니다.

 

 

 

import pandas as pd

dict_test = {
    'col1': [1, 2, 3, 4, 5],
    'col2': [2, 3, 4, 5, 6],
}
df_test = pd.DataFrame(dict_test)


df_test_1 = df_test

df_test_1.loc[:, 'col3'] = 3

print(df_test)
print(df_test_1)



-- Result
   col1  col2  col3
0     1     2     3
1     2     3     3
2     3     4     3
3     4     5     3
4     5     6     3

   col1  col2  col3
0     1     2     3
1     2     3     3
2     3     4     3
3     4     5     3
4     5     6     3

 

결과 출력을 해보면 df_test, df_test_1 모두에 col3가 생긴 것을 볼 수 있습니다.

 

DataFrame을 다른 변수에 할당하면 단순히 새로운 변수에만 DataFrame을 복사해서 넣는 것이 아니라 원본 DataFrame을 참조하는 형태로 DataFrame을 할당받게 됩니다.

 

 

 

 

 

 

 

import pandas as pd

dict_test = {
    'col1': [1, 2, 3, 4, 5],
    'col2': [2, 3, 4, 5, 6],
}
df_test = pd.DataFrame(dict_test)


df_test_1 = df_test.copy()

df_test_1.loc[:, 'col3'] = 3

print(df_test)
print(df_test_1)



-- Result
   col1  col2
0     1     2
1     2     3
2     3     4
3     4     5
4     5     6

   col1  col2  col3
0     1     2     3
1     2     3     3
2     3     4     3
3     4     5     3
4     5     6     3

 

이를 방지하기 위해선 copy() method를 사용할 수 있습니다.

 

- df_test_1 = df_test.copy()

copy() method는 DataFrame을 복사해서 df_test_1에 할당하게 됩니다.

 

따라서 df_test_1은 df_test를 참조하는 것이 아닌 독자적인 DataFrame이 되는 것이죠.

 

그래서 col3이 df_test_1에만 생긴 것을 알 수 있습니다.

 

 

 

 

 

이러한 특성 때문에 발생하는 에러가 하나 있습니다.

 

 

 

import pandas as pd

dict_test = {
    'col1': [1, 2, 3, 4, 5],
    'col2': [2, 3, 4, 5, 6],
}
df_test = pd.DataFrame(dict_test)


con = (df_test['col1'] <= 3)
df_test_1 = df_test.loc[con, :]

df_test_1.loc[:, 'col3'] = 3

 

위 코드를 실행하면 아래와 같은 에러가 뜹니다.

 

SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame.

 

 

 

위 코드를 살펴봅시다.

 

con = (df_test['col1'] <= 3)
df_test_1 = df_test.loc[con, :]

 

위 코드에서는 df_test_1에 df_test를 할당할 때 그냥 df_test 자체를 할당하는게 아니라 어떠한 조건을 적용해서 특정 index의 row만을 할당했습니다.

 

 

df_test_1.loc[:, 'col3'] = 3

 

그리고 df_test_1에 col3를 추가했습니다.

 

이런 경우 df_test_1에 col3를 추가했으니 df_test에도 col3가 추가될까요?

 

정답은 아니오 입니다.

 

df_test_1에 할당된 DataFrame은 df_test의 일부이기 때문에 df_test_1에 할당된 DataFrame은 새로운 DataFrame입니다.

 

 

import pandas as pd

dict_test = {
    'col1': [1, 2, 3, 4, 5],
    'col2': [2, 3, 4, 5, 6],
}
df_test = pd.DataFrame(dict_test)


con = (df_test['col1'] <= 3)
df_test_1 = df_test.loc[con, :]

df_test_1.loc[:, 'col3'] = 3

print(df_test)
print(df_test_1)



-- Result
   col1  col2
0     1     2
1     2     3
2     3     4
3     4     5
4     5     6

   col1  col2  col3
0     1     2     3
1     2     3     3
2     3     4     3

 

그래서 결과를 출력해보면 위처럼 df_test_1에만 col3가 생긴 것을 알 수 있습니다.

 

 

 

SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame.

 

따라서 위 에러는 이러한 상황을 주의하라고 출력되는 에러 메세지 입니다.

 

 

위같은 에러메세지를 방지하려면 코드를 아래와 같이 수정하면 됩니다.

 

import pandas as pd

dict_test = {
    'col1': [1, 2, 3, 4, 5],
    'col2': [2, 3, 4, 5, 6],
}
df_test = pd.DataFrame(dict_test)


con = (df_test['col1'] <= 3)
df_test_1 = df_test.loc[con, :].copy()

df_test_1.loc[:, 'col3'] = 3

print(df_test)
print(df_test_1)



-- Result
   col1  col2
0     1     2
1     2     3
2     3     4
3     4     5
4     5     6

   col1  col2  col3
0     1     2     3
1     2     3     3
2     3     4     3

 

- df_test_1 = df_test.loc[con, :].copy()

이렇게 copy() method를 이용해서 명확하게 DataFrame을 복사해주는 것입니다.

 

그러면 SettingWithCopyWarning 에러가 사라지게 됩니다.

 

 

 

 

 

728x90
반응형