[Pandas] groupby
Pandas groupby, groupby 집계, split-apply-combine
정의
DataFrame.groupby(key) 는 데이터를 그룹으로 나누고 (split), 각 그룹에 함수를 적용 (apply), 결과를 합쳐 (combine) 새 DataFrame 으로 만드는 split-apply-combine 패턴의 구현.
SQL 의 GROUP BY 와 같은 개념, 더 풍부한 API.
시각화
기본
df.groupby('city')['salary'].mean()
df.groupby('city')['salary'].sum()
df.groupby('city').agg({'salary': 'mean', 'age': 'max'})
df.groupby(['city', 'dept']).size()
python
import pandas as pd
df = pd.DataFrame({
'city': ['Seoul', 'Busan', 'Seoul', 'Busan', 'Seoul'],
'dept': ['A', 'A', 'B', 'B', 'A'],
'salary': [3000, 4000, 5000, 4500, 3500],
})
print(df.groupby('city')['salary'].mean()) 결과
city
Busan 4250.0
Seoul 3833.333333
Name: salary, dtype: float64| city | salary mean |
|---|---|
| Busan | 4250.00 |
| Seoul | 3833.33 |
여러 컬럼 그룹
df.groupby(['city', 'dept'])['salary'].mean()
python
import pandas as pd
df = pd.DataFrame({
'city': ['Seoul', 'Busan', 'Seoul', 'Busan', 'Seoul'],
'dept': ['A', 'A', 'B', 'B', 'A'],
'salary': [3000, 4000, 5000, 4500, 3500],
})
print(df.groupby(['city', 'dept'])['salary'].mean()) 결과
city dept
Busan A 4000.0
B 4500.0
Seoul A 3250.0
B 5000.0
Name: salary, dtype: float64결과는 MultiIndex Series. .reset_index() 또는 .unstack() 으로 평탄화.
agg 로 여러 함수
df.groupby('city').agg({
'salary': ['mean', 'sum', 'max'],
'age': 'mean',
})
Pandas agg 참고.
자주 쓰는 메서드
| 메서드 | 의미 |
|---|---|
.sum(), .mean(), .median(), .std() | 통계 |
.min(), .max() | 극값 |
.count() | non-null 개수 |
.size() | 그룹별 행 수 (NaN 포함) |
.first(), .last(), .nth(i) | 위치 기반 |
.head(n), .tail(n) | 그룹 내 상위/하위 N |
.cumsum(), .cumcount() | 누적 |
.transform(fn) | 그룹별 변환, 원본 shape 유지 |
.apply(fn) | 임의 함수, 가장 유연 |
.filter(fn) | 그룹 단위 필터 |
groupby 결과는 lazy
g = df.groupby('city') # GroupBy 객체만, 아직 계산 안 함
g.groups # {'Seoul': [0, 2, 4], 'Busan': [1, 3]}
g.get_group('Seoul') # 한 그룹의 DataFrame
list(g) # [(name, df), ...]
명시적으로 집계 함수를 호출해야 계산 발생.
그룹별 정렬 후 head (top N per group)
df.sort_values(['city', 'salary'], ascending=[True, False]) \
.groupby('city').head(2)
각 city 별 salary 상위 2 명.
그룹별 정규화 (transform)
df['salary_z'] = df.groupby('dept')['salary'].transform(
lambda x: (x - x.mean()) / x.std()
)
각 부서 내에서 z-score, 원본 DataFrame 의 shape 유지.
함정
1. as_index 의 의미
df.groupby('city')['salary'].mean() # MultiIndex Series
df.groupby('city', as_index=False)['salary'].mean() # DataFrame, city 가 컬럼
2. NaN 그룹
기본은 NaN 그룹 제외. dropna=False 로 포함 가능.
df.groupby('city', dropna=False)['salary'].mean()
3. groupby + apply 의 느림
df.groupby('x').apply(complex_function)
# apply 는 가장 느림, 가능하면 agg / transform / 벡터 연산
4. SettingWithCopyWarning
group = df.groupby('city').get_group('Seoul')
group['new'] = 1 # ⚠️
group = group.copy()
Named Aggregation (NamedAgg)
pandas 0.25+ 의 명시적 이름 집계. MultiIndex 컬럼 없이 깔끔한 결과.
result = df.groupby('city').agg(
mean_salary=('salary', 'mean'),
max_age=('age', 'max'),
total=('salary', 'sum'),
count=('name', 'count'),
)
# 컬럼: mean_salary, max_age, total, count
기존 agg({'salary': ['mean', 'sum']}) 의 MultiIndex 컬럼을 회피.
split-apply-combine 시각화
flowchart LR
Raw["원본 DataFrame"] -->|"groupby(key)"| Split["Split: 그룹 분리"]
Split -->|"agg / transform"| Apply["Apply: 함수 적용"]
Apply --> Combine["Combine: 결과 합산"]
Combine --> Out["집계 DataFrame"]
시계열 groupby: resample
DatetimeIndex 가 있을 때 시간 단위 groupby.
df = df.set_index('date')
df.resample('ME')['revenue'].sum() # 월별 합계
df.resample('W')['sales'].mean() # 주별 평균
df.resample('QE')['profit'].agg(['sum', 'mean'])
| alias | 의미 |
|---|---|
ME | 월말 (Month End) |
QE | 분기말 (Quarter End) |
W | 주 (Week, 일요일 기준) |
D | 일 (Day) |
h | 시간 |
pandas-resample 참고.
Categorical 컬럼과 groupby
df['dept'] = pd.Categorical(df['dept'], categories=['A', 'B', 'C'])
result = df.groupby('dept', observed=False)['salary'].mean()
# 등장하지 않은 카테고리도 NaN 으로 포함
observed=False: 등장하지 않은 카테고리도 결과 포함. pandas 2.x 기본값 observed=True.
성능 팁
# 느림: apply (Python loop)
df.groupby('city').apply(lambda g: g['salary'].mean())
# 빠름: 내장 벡터 집계
df.groupby('city')['salary'].mean()
# 매우 큰 데이터: Categorical 지정 + observed=True
df['city'] = df['city'].astype('category')
df.groupby('city', observed=True)['salary'].mean()
| 방법 | 속도 | 유연성 |
|---|---|---|
.sum() / .mean() | 매우 빠름 | 낮음 |
.agg(dict) | 빠름 | 중간 |
.transform(fn) | 중간 | 높음 |
.apply(fn) | 느림 | 매우 높음 |
TIP
apply 회피: transform, agg, 벡터 연산으로 대체 가능한지 먼저 확인. pandas-performance 참고.
참고
이 글의 용어 (7개)
- [Pandas] 성능 / 메모리 최적화pandas
- 정의 pandas 의 흔한 성능 함정과 최적화 패턴. 벡터화 + dtype 선택 + 알고리즘 의 조합이 핵심. 사용 상황 | 상황 | 권장 접근 | |:---|:---| | 단순…
- [Pandas] agg / aggregatepandas
- 정의 는 여러 집계 함수를 한 번에 적용 한다. , , 모두에서 사용 가능. 는 같은 함수의 별칭. agg 처리 흐름 사용 상황 | 상황 | 패턴 | |:---|:---| | 전…
- [Pandas] Categoricalpandas
- 정의 Categorical 은 제한된 고유값 만 가질 수 있는 dtype. 내부적으로 정수 코드로 저장되어 메모리 절약 과 속도 향상 을 동시에 달성한다. 고유값 수가 적고(lo…
- [Pandas] DataFramepandas
- 정의 은 2차원 레이블 테이블. 각 열이 , 모든 열이 같은 (행 라벨) 를 공유. SQL 테이블 / Excel 시트 / R data.frame 의 Python 대응체. 구조 시…
- [Pandas] pivot_tablepandas
- 정의 는 의 확장. 집계 함수를 동반 해 중복 (index, columns) 도 처리. Excel 의 피벗 테이블과 가장 가까운 기능. pivottable 처리 흐름 사용 상황 …
- [Pandas] resamplepandas
- 정의 는 시계열 데이터를 다른 빈도 (월별, 일별, 시간별 등) 로 재샘플링하면서 집계한다. 의 시계열 버전. DatetimeIndex (또는 으로 datetime 컬럼) 이 필…
- [Pandas] transform / applypandas
- 정의 | 메서드 | 입력 | 출력 | 용도 | |:---|:---|:---|:---| | | 그룹 | 같은 shape | 정규화, 보충 | | | 그룹 | 임의 shape | 가…
이 개념을 다룬 위키 페이지 (36)
- wiki[Pandas] agg / aggregate
- wiki[Pandas] apply / map
- wiki[Pandas] Categorical
- wiki[Pandas] concat
- wiki[Pandas] crosstab
- wiki[Pandas] cumsum / cummax / cummin / cumprod
- wiki[Pandas] cut / qcut
- wiki[Pandas] date_range / Timestamp
- wiki[Pandas] drop_duplicates / duplicated
- wiki[Pandas] dropna / fillna
- wiki[Pandas] .dt accessor
- wiki[Pandas] explode
- wiki[Pandas] idxmax / idxmin
- wiki[Pandas] iterrows / itertuples
- wiki[Pandas] melt
- wiki[Pandas] merge_asof
- wiki[Pandas] MultiIndex
- wiki[Pandas] nlargest / nsmallest / rank
- wiki[Pandas] 개요
- wiki[Pandas] pipe / method chaining
- wiki[Pandas] pipe / method chaining
- wiki[Pandas] pivot
- wiki[Pandas] pivot_table
- wiki[Pandas] resample
- wiki[Pandas] rolling / expanding
- wiki[Pandas] sample
- wiki[Pandas] SettingWithCopyWarning
- wiki[Pandas] shift / diff / pct_change
- wiki[Pandas] sort_values / sort_index
- wiki[Pandas] stack / unstack
- wiki[Pandas] to_datetime
- wiki[Pandas] transform / apply
- wiki[Pandas] unique / nunique
- wiki[Pandas] value_counts
- wiki[SQL] DML
- wiki[SQL] GROUP BY
💬 댓글