라떼군 이야기
Pandas groupby.apply의 DeprecationWarning: grouping columns 경고 해결 방법
Problem
Pandas 라이브러리를 2.2.0 버전 이상으로 업데이트한 후, 기존에 문제없이 작동하던 데이터 처리 스크립트에서 갑자기 DeprecationWarning이 발생하는 경우가 있습니다. 구체적으로 df.groupby(...).apply(...)를 사용할 때 다음과 같은 경고 메시지가 출력됩니다.
DeprecationWarning: DataFrameGroupBy.apply operated on the grouping columns. This behavior is deprecated, and in a future version of pandas the grouping columns will be excluded from the operation.
이는 그룹화의 기준이 된 컬럼(grouping columns)이 apply 함수 내부로 전달되는 방식이 변경될 예정임을 알리는 경고입니다.
Background
Pandas 2.2.0 이전 버전에서는 groupby 연산을 수행할 때, 각 그룹별로 생성된 서브 데이터프레임 안에 ‘그룹화의 기준이 된 컬럼’이 그대로 포함되어 있었습니다. 예를 들어 df.groupby('category').apply(func)를 실행하면 func에 전달되는 데이터프레임에는 category 컬럼이 들어있었습니다.
하지만 이는 sum()이나 mean() 같은 전체 집계 함수를 사용할 때, 의도치 않게 그룹 키(예: 숫자 ID)까지 연산에 포함시켜 결과를 왜곡하는 버그를 유발하곤 했습니다. Pandas 개발팀은 버전 3.0부터는 그룹 키를 연산 대상에서 기본적으로 제외하기로 결정했으며, 현재 버전(2.2.x)에서는 이 변경 사항을 미리 알리기 위해 include_groups=False를 명시하지 않으면 경고를 띄우도록 변경되었습니다.
Solution
이 경고를 해결하고 향후 Pandas 버전과의 호환성을 유지하기 위한 방법은 크게 세 가지가 있습니다.
1. include_groups=False 파라미터 추가 (권장)
가장 간단하고 권장되는 방법은 apply 메서드에 include_groups=False를 명시적으로 전달하는 것입니다. 이는 Pandas 3.0의 기본 동작과 동일하게 그룹화 컬럼을 연산에서 제외합니다.
import pandas as pd
# 예시 데이터 생성
data = {
'Category': ['A', 'A', 'B', 'B'],
'Value': [10, 20, 30, 40],
'ID': [1, 1, 2, 2]
}
df = pd.DataFrame(data)
# 기존 코드 (경고 발생)
# result = df.groupby('Category').apply(lambda x: x.sum())
# 해결 방법: include_groups=False 추가
# 그룹핑 기준인 'Category' 컬럼은 sum() 연산에서 제외됨
result = df.groupby('Category').apply(lambda x: x.sum(), include_groups=False)
print(result)
# 출력 결과:
# Value ID
# Category
# A 30 2
# B 70 4
2. 연산에 필요한 컬럼 명시적 선택
groupby 객체에서 연산에 필요한 컬럼만 미리 선택한 후 apply를 호출하면, 그룹핑 컬럼이 포함될 여지가 없으므로 경고가 사라집니다.
# 'Category'로 그룹화하되, 'Value'와 'ID' 컬럼만 선택하여 연산 수행
result = df.groupby('Category')[['Value', 'ID']].apply(lambda x: x.sum())
print(result)
3. 그룹핑 컬럼을 인덱스로 설정
데이터프레임의 인덱스를 미리 설정하여 그룹화하는 방법도 있습니다. 이 경우 그룹핑 컬럼이 데이터 영역(columns)이 아닌 인덱스(index)에 위치하므로 연산 대상에서 자연스럽게 제외됩니다.
# 'Category'를 인덱스로 설정 후 그룹화
result = df.set_index('Category').groupby(level='Category').apply(lambda x: x.sum())
print(result)
Deep Dive
include_groups=True(기존 동작)와 include_groups=False(새로운 동작)의 차이는 단순한 경고 제거 이상의 의미가 있습니다. 특히 그룹핑 컬럼이 수치형 데이터일 때 결과값 자체가 달라질 수 있습니다.
예를 들어, 숫자 ID 컬럼으로 그룹화하여 평균(mean)을 구한다고 가정해 봅시다.
- 기존 동작 (
True):ID컬럼도 데이터에 포함되므로,ID의 평균값(자기 자신)이 결과에 포함됩니다. - 새로운 동작 (
False):ID컬럼은 그룹 식별자로만 사용되고 연산에서 제외되므로, 실제 분석 대상인 다른 수치 컬럼들의 평균만 계산됩니다.
따라서 include_groups=False를 사용하는 것은 단순히 경고를 끄는 것이 아니라, 데이터 분석의 논리적 오류를 방지하고 더 명확한 코드를 작성하는 방향입니다.
Conclusion
Pandas의 DeprecationWarning은 버전 3.0에서의 변화를 예고하는 중요한 신호입니다. groupby().apply() 사용 시 include_groups=False를 추가함으로써 경고를 해결할 뿐만 아니라, 그룹핑 컬럼이 연산에 불필요하게 포함되는 부작용을 막을 수 있습니다. 코드를 최신 상태로 유지하고 잠재적인 버그를 예방하기 위해 이 옵션을 적극적으로 사용하는 것을 권장합니다.