Pandas의 groupby()는 데이터 분석에 있어 가장 핵심적인 도구 중 하나입니다. 데이터를 그룹별로 나누고(split), 각 그룹에 연산을 적용하고(apply), 결과를 결합(combine)하는 방식으로 작동합니다. 이번 포스트에서는 groupby()의 기본 사용법부터 agg, apply, transform 등 고급 기능까지 모두 다뤄보겠습니다.
groupby 작동 방식
groupby()는 내부적으로 아래 세 가지 단계를 거쳐 동작합니다:
- Split (분할): 지정한 컬럼의 값에 따라 데이터를 여러 그룹으로 나눕니다.
- Apply (적용): 각 그룹에 대해 함수나 연산을 적용합니다 (mean(), sum(), 사용자 정의 함수 등).
- Combine (결합): 그룹별 결과를 하나의 객체로 합칩니다.
이러한 구조는 SQL의 GROUP BY와 유사하지만, 더 유연한 연산과 다양한 방식으로 결과를 다룰 수 있다는 점에서 차별화됩니다.
🧩 Split 형태로 직접 활용하기
groupby()로 나눈 객체는 집계를 하지 않더라도, 나눈 그룹을 직접 다룰 수 있습니다.
grouped = df.groupby('subject')
# 그룹 이름과 인덱스를 딕셔너리로 확인
print(grouped.groups)
# 특정 그룹만 가져오기
math_df = grouped.get_group('math')
# 루프를 통해 그룹별 처리
for name, group in grouped:
print(f"[{name}]")
print(group)
이러한 split-only 형태의 활용은 시각화, 파일 저장, 그룹별 조건 처리 등 다양한 실전 작업에서 유용하게 쓰입니다.
groupby 객체에서 split된 각 그룹에 대해 개별적으로 apply()나 lambda 함수를 적용할 수 있습니다. 예시로 설명드릴게요.
예시
import pandas as pd
df = pd.DataFrame({
'team': ['A', 'A', 'B', 'B', 'C'],
'score': [80, 90, 70, 60, 85]
})
# 그룹별로 서로 다른 함수 적용
def custom_logic(group):
if group.name == 'A':
return group['score'] * 2
elif group.name == 'B':
return group['score'] + 10
else:
return group['score'] - 5
df['modified'] = df.groupby('team').apply(custom_logic).reset_index(drop=True)
포인트
- group.name으로 현재 그룹명이 무엇인지 접근 가능.
- groupby().apply() 내부에서 그룹별로 다른 연산을 수행할 수 있음.
- reset_index(drop=True)는 apply()가 생성한 다중 인덱스를 없애는 데 유용.
기본 사용법: 그룹별 평균 구하기
import pandas as pd
# 예제 데이터프레임
students = pd.DataFrame({
'name': ['혜선', '종훈', '혜선', '종훈', '소원'],
'subject': ['math', 'math', 'english', 'english', 'math'],
'score': [90, 85, 92, 88, 75]
})
# 과목별 평균 점수
students.groupby('subject')['score'].mean()
여러 컬럼으로 그룹화
students.groupby(['name', 'subject'])['score'].mean()
여러 컬럼으로 그룹화하면 다중 인덱스(MultiIndex) 형태의 결과가 나옵니다.
다양한 집계 함수: agg()
agg()는 하나 혹은 여러 개의 집계 함수를 적용할 수 있습니다.
students.groupby('subject')['score'].agg(['mean', 'max', 'min'])
또는 컬럼별로 다른 집계 함수를 지정할 수도 있습니다.
students.groupby('subject').agg({
'score': 'mean',
'name': 'count'
})
고급 집계: 사용자 정의 함수와 lambda
students.groupby('subject')['score'].agg(lambda x: x.max() - x.min())
각 과목의 점수 범위(최대-최소)를 계산합니다.
전체 데이터프레임에 apply() 사용
apply()는 그룹별로 전체 DataFrame에 사용자 정의 함수를 적용할 때 유용합니다.
def zscore(x):
return (x - x.mean()) / x.std()
students.groupby('subject')['score'].apply(zscore)
그룹별 값 유지: transform()
transform()은 그룹별 계산 결과를 원본과 동일한 길이로 반환할 때 사용합니다. 즉, 결과를 원본 DataFrame에 바로 붙이기 좋습니다.
students['subject_avg'] = students.groupby('subject')['score'].transform('mean')
🧩 그룹 객체 다루기
grouped = students.groupby('subject')
print(grouped.groups) # 그룹 정보 딕셔너리
print(grouped.get_group('math')) # 특정 그룹 가져오기
정리
마무리 Tip
- 단순한 요약 통계: agg()
- 그룹별 처리 후 다시 합치고 싶을 때: transform()
- 그룹별 복잡한 로직을 적용하고 싶을 때: apply()
- 집계를 하지 않고 그룹 단위로 나눈 데이터를 직접 다루고 싶다면 .get_group(), .groups, for 루프를 활용해보세요.
'파이썬 > 데이터프레임 다루기' 카테고리의 다른 글
Pandas at vs loc – 헷갈리지 말고 정확히 쓰자! (0) | 2025.03.25 |
---|---|
이터레이터 vs 제너레이터: 파이썬 반복의 핵심 이해하기 (0) | 2025.03.24 |
Pandas pivot_table() 완전 정복 (0) | 2025.03.24 |
Pandas 데이터 포맷 전환: melt()와 pivot() 완전 정리 (0) | 2025.03.24 |
Pandas 멀티인덱스 다루기: stack()과 unstack() 정리 (0) | 2025.03.24 |