본문 바로가기
C.W.K.
Stream
Lesson 05 of 07 · published

GroupBy — Split, Apply, Combine

~14 min · pandas, groupby, aggregation

Level 0구경꾼
0 XP0/47 lessons0/11 achievements
0/120 XP to next level120 XP to go0% complete

Tabular 분석에서 제일 쓸모 많은 패턴 하나

Split-apply-combine — row 를 그룹으로 쪼개고, 그룹마다 함수를 적용하고, 그룹별 결과를 한 테이블로 다시 모으는 패턴이야. 실전에서 만나는 tabular 질문의 절대 다수가 이 틀 안에 들어와. Pandas 에선 df.groupby(...) 가 그 문이고, 이걸 제대로 익히는 게 Pandas 사용자로서 할 수 있는 가장 남는 투자 중 하나야.

"Apply" 의 세 갈래

  • Aggregate — 그룹당 값 하나 (sum, mean, median, count). 결과는 그룹당 한 row.
  • Transform — 그룹 안에서 계산된 row 당 값 하나 (store 안에서의 z-score, customer 안에서의 rank). 결과는 입력과 같은 모양.
  • Filter — 그룹 단위 시험으로 그룹 전체를 남기거나 버리기 ("이번 달 주문 100건 넘는 store 만").

Named aggregation 이 modern 스타일

옛날 코드는 dict-of-list (.agg({'amount': ['sum', 'mean']})) 를 써서 못생긴 multi-index column 을 만들어. 새 코드는 named aggregation 을 써: .agg(revenue=('amount_usd', 'sum'), orders=('order_id', 'nunique')). 결과 column 에 명확한 이름이 붙고, 코드가 consumer 와 맺은 contract 처럼 읽혀.

Code

Aggregate, transform, filter — DataFrame 하나, 패턴 셋·python
import pandas as pd
import numpy as np

rng = np.random.default_rng(7)
df = pd.DataFrame({
    'store':      rng.choice(['A', 'B', 'C'], 1000),
    'customer':   rng.integers(1, 200, 1000),
    'order_id':   [f'O{i:05d}' for i in range(1000)],
    'amount_usd': rng.uniform(5, 500, 1000).round(2),
})

# Aggregate — store 당 한 row
summary = df.groupby('store', as_index=False).agg(
    revenue=('amount_usd', 'sum'),
    avg_ticket=('amount_usd', 'mean'),
    orders=('order_id', 'nunique'),
    customers=('customer', 'nunique'),
)

# Transform — 각 store 안에서 amount 의 z-score
df['amount_z_in_store'] = (
    df.groupby('store')['amount_usd']
      .transform(lambda s: (s - s.mean()) / s.std())
)

# Filter — 총 매출 $50,000 넘는 store 만
big_stores = df.groupby('store').filter(lambda g: g['amount_usd'].sum() > 50_000)

External links

Exercise

위 예시 DataFrame 으로 세 가지를 계산해 봐: (1) store 별 median ticket size, (2) customer 별 모든 store 합산 총 spend, (3) 각 store 에서 금액이 가장 큰 주문 row. 힌트: #3 은 groupby('store').apply(lambda g: g.loc[g['amount_usd'].idxmax()]) 로도 되지만 df.sort_values(['store', 'amount_usd']).drop_duplicates('store', keep='last') 가 더 빨라.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.