라떼군 이야기


Pandas groupby.apply 경고: DeprecationWarning 해결과 include_groups 파라미터 이해하기

Problem

Pandas 2.2.0 버전 이상을 사용하는 환경에서 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.

코드는 정상적으로 실행되어 결과가 나오지만, 매번 경고가 출력되어 로그를 확인하기 어렵게 만들며, 향후 Pandas 버전 업데이트 시 코드가 깨질 위험이 있다는 것을 의미합니다.

Background

이 경고는 Pandas가 2.2.0에서 3.0으로 넘어가는 과도기에 도입된 변경 사항 때문에 발생합니다. 기존 Pandas 버전(2.2.0 미만)에서는 groupby 연산을 수행할 때, 그룹화의 기준이 된 컬럼(Grouping Columns)도 apply 함수 내부로 전달되는 데이터프레임에 포함되었습니다.

하지만 이는 의도치 않은 버그를 유발할 수 있습니다. 예를 들어, 숫자형 ID로 그룹화를 하고 전체 평균(mean)을 구할 때, 그룹화 기준인 ID 값까지 평균 계산에 포함되는 문제가 발생할 수 있습니다. 이를 해결하기 위해 Pandas 개발팀은 향후 버전에서 그룹화 컬럼을 연산 대상에서 기본적으로 제외하기로 결정했습니다.

Solution

이 경고를 해결하고 미래의 Pandas 버전에 대비하는 가장 확실한 방법은 두 가지가 있습니다.

방법 1: include_groups=False 파라미터 사용 (권장)

가장 간단한 해결책은 apply 메서드에 include_groups=False를 명시적으로 전달하는 것입니다. 이는 “그룹화 기준 열을 연산에 포함하지 않겠다"고 선언하는 것으로, Pandas 3.0의 기본 동작을 미리 적용하는 셈입니다.

import pandas as pd

# 예제 데이터 생성
df = pd.DataFrame({
    'Category': ['A', 'A', 'B', 'B'],
    'Value': [10, 20, 30, 40],
    'Other': [1, 2, 3, 4]
})

# 기존 방식 (경고 발생 가능)
# result = df.groupby('Category').apply(lambda x: x['Value'].sum())

# 해결 방식: include_groups=False 추가
# 그룹화 기준인 'Category' 열은 lambda 함수 내부의 x에 포함되지 않음
result = df.groupby('Category').apply(
    lambda x: x['Value'].sum(), 
    include_groups=False
)

print(result)

방법 2: 연산할 컬럼을 명시적으로 선택

apply를 호출하기 전에 필요한 컬럼만 명시적으로 선택(Slicing)하면, 그룹화 컬럼이 자연스럽게 제외되므로 경고가 발생하지 않습니다. 코드의 가독성을 높이는 좋은 습관이기도 합니다.

# 해결 방식 2: 필요한 컬럼만 선택 후 apply 적용
# 'Category'로 그룹화하되, ['Value', 'Other'] 컬럼만 가져와서 연산
result = df.groupby('Category')[['Value', 'Other']].apply(
    lambda x: x.sum()
)

print(result)

방법 3: 인덱스 설정 (Set Index)

그룹화 컬럼을 인덱스로 설정한 뒤 그룹화를 수행하면, 해당 컬럼은 데이터 영역이 아닌 인덱스 영역에 존재하게 되어 연산에서 제외됩니다.

# 해결 방식 3: set_index 사용
result = df.set_index('Category').groupby(level='Category').apply(
    lambda x: x.sum()
)

Deep Dive

왜 이런 변경이 일어났는지 이해하기 위해 간단한 np.mean 예시를 살펴보겠습니다. 만약 그룹화 컬럼이 숫자형 데이터라면, 기존 방식(include_groups=True)은 심각한 논리적 오류를 범할 수 있습니다.

import pandas as pd
import numpy as np

df = pd.DataFrame({'ID': [1, 1, 2, 2], 'Value': [10, 20, 30, 40]})

# include_groups=True (기존 동작)
# ID가 1인 그룹의 평균을 구할 때 (1 + 10 + 20) / 3 = 10.33 이 계산됨 (잘못된 결과)
# df.groupby('ID').apply(np.mean)

# include_groups=False (새로운 동작)
# ID가 1인 그룹의 평균은 Value만 계산: (10 + 20) / 2 = 15.0 (올바른 결과)
# df.groupby('ID').apply(np.mean, include_groups=False)

이처럼 include_groups=False는 단순히 경고를 끄는 것을 넘어, 데이터 분석의 정확성을 보장하기 위한 필수적인 설정입니다. 만약 apply 함수 내부에서 그룹화 컬럼의 값이 반드시 필요하다면, 해당 컬럼을 인덱스로 접근하거나 별도의 로직으로 처리해야 합니다.

Conclusion

Pandas의 DeprecationWarning은 곧 다가올 버전 3.0에서의 변화를 예고합니다. include_groups=False를 사용하여 경고를 제거하고, 그룹화 컬럼이 연산에 불필요하게 개입하는 것을 방지하세요. 명시적으로 컬럼을 선택하여 연산하는 습관을 들이는 것도 좋은 대안입니다.

References

Open to collaboration Get in touch →