[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()
참고
이 글의 용어 (4개)
- [Pandas] agg / aggregatepandas
- 정의 는 여러 집계 함수를 한 번에 적용 한다. , , 모두에서 사용 가능. 는 같은 함수의 별칭. 다양한 형태 단일 함수 함수 리스트 <CodeWithOutput languag…
- [Pandas] DataFramepandas
- 정의 은 2차원 레이블 테이블. 각 열이 , 모든 열이 같은 (행 라벨) 를 공유. SQL 테이블 / Excel 시트 / R data.frame 의 Python 대응체. 생성 <…
- [Pandas] pivot_tablepandas
- 정의 는 의 확장. 집계 함수를 동반 해 중복 (index, columns) 도 처리. Excel 의 피벗 테이블과 가장 가까운 기능. 기본 <CodeWithOutput lang…
- [Pandas] transform / applypandas
- 정의 | 메서드 | 입력 | 출력 | 용도 | |:---|:---|:---|:---| | | 그룹 | 같은 shape | 정규화, 보충 | | | 그룹 | 임의 shape | 가…
이 개념을 다룬 위키 페이지 (19)
- wiki[Pandas] agg / aggregate
- wiki[Pandas] crosstab
- wiki[Pandas] cumsum / cummax / cummin / cumprod
- wiki[Pandas] cut / qcut
- wiki[Pandas] dropna / fillna
- wiki[Pandas] explode
- wiki[Pandas] idxmax / idxmin
- wiki[Pandas] MultiIndex
- wiki[Pandas] nlargest / nsmallest / rank
- wiki[Pandas] 개요
- wiki[Pandas] pivot_table
- wiki[Pandas] resample
- wiki[Pandas] rolling / expanding
- wiki[Pandas] sample
- wiki[Pandas] transform / apply
- wiki[Pandas] value_counts
- wikiSQL
- wiki[SQL] DML
- wiki[SQL] GROUP BY
💬 댓글