워로디스

Pandas. groupby 자주 쓰이는 패턴 본문

Data Science/Pandas

Pandas. groupby 자주 쓰이는 패턴

워로디스 2026. 10. 19. 22:31

pandas의 groupby()는 데이터 분석에서 정말 자주 쓰이는 기능입니다.

핵심은 특정 컬럼을 기준으로 데이터를 그룹으로 묶고, 그룹별로 계산하는 것입니다.

실무에서 자주 사용하는 패턴 6가지만 알아도 대부분의 기본적인 집계 작업을 처리할 수 있습니다.

0. 예제 데이터

아래 데이터를 기준으로 설명하겠습니다.

import pandas as pd

df = pd.DataFrame({    
    "region": ["서울", "서울", "부산", "부산", "서울", "부산"],    
    "category": ["식품", "가전", "식품", "가전", "식품", "식품"],    
    "customer": ["A", "B", "A", "C", "B", "D"],    
    "sales": [100, 300, 200, 400, 150, 100]
})
  region category customer sales
0 서울 식품 A 100
1 서울 가전 B 300
2 부산 식품 A 200
3 부산 가전 C 400
4 서울 식품 B 150
5 부산 식품 D 100

1. 가장 기본: 그룹별 합계, 평균

가장 많이 사용하는 형태입니다.

# 지역별 매출 합계

df.groupby("region")["sales"].sum()

결과:

region
부산    700
서울    550
Name: sales, dtype: int64

평균, 최댓값, 최솟값도 똑같은 방식입니다.

df.groupby("region")["sales"].mean()
df.groupby("region")["sales"].max()
df.groupby("region")["sales"].min()

기본 구조

df.groupby("그룹기준")["계산할컬럼"].집계함수()

2. 여러 컬럼을 기준으로 그룹화

지역뿐만 아니라 상품 카테고리별로도 매출을 나누고 싶을 때 사용합니다.

df.groupby(["region", "category"])["sales"].sum()

결과:

region  category
부산      가전       400
          식품       300
서울      가전       300
          식품       250

여기서 reset_index()를 붙이면 일반적인 DataFrame 형태로 바꿀 수 있습니다.

df.groupby(["region", "category"])["sales"].sum().reset_index()
region category sales
부산 가전 400
부산 식품 300
서울 가전 300
서울 식품 250

같은 결과를 더 간결하게 얻는 방법도 있습니다.

df.groupby(    
    ["region", "category"],    
    as_index=False
)["sales"].sum()

실무에서는 후속 처리를 쉽게 하려고 as_index=False를 자주 사용합니다.

3. agg(): 여러 통계를 한 번에 계산

특히 추천하는 패턴입니다. 합계, 평균, 건수 등을 한 번에 구할 수 있습니다.

df.groupby("region").agg(    
    total_sales=("sales", "sum"),    
    avg_sales=("sales", "mean"),    
    max_sales=("sales", "max")
)

결과:

region total_sales avg_sales max_sales
부산 700 233.33 400
서울 550 183.33 300

문법은 다음과 같습니다.

새로운컬럼명=("원본컬럼명", "집계함수")

조금 더 실무적인 예제입니다.

summary = df.groupby("region", as_index=False).agg(    
    total_sales=("sales", "sum"),    
    avg_sales=("sales", "mean"),    
    order_count=("sales", "size"),    
    customer_count=("customer", "nunique")
)

이렇게 하면 지역별 매출 합계, 평균, 주문 건수, 고유 고객 수를 한 번에 구할 수 있습니다.

4. size(), count(), nunique(): 개수 세기

세 함수의 차이를 알아두면 좋습니다.

함수 의미
size() 그룹에 속한 전체 행 개수
count() 특정 컬럼에서 결측치가 아닌 값의 개수
nunique() 특정 컬럼의 고유한 값 개수

 

# 지역별 전체 행 개수
df.groupby("region").size()
# 지역별 sales가 결측치가 아닌 행 개수
df.groupby("region")["sales"].count()
# 지역별 고유 고객 수
df.groupby("region")["customer"].nunique()

특히 size()와 count()는 결측치(NaN)가 있을 때 결과가 달라질 수 있다는 점을 기억하면 됩니다.

5. transform(): 그룹별 계산 결과를 원본 행에 붙이기

agg()만큼 알아두면 유용한 함수입니다.

일반적인 groupby() 집계는 그룹별로 행이 줄어들지만, transform()은 원본 DataFrame과 같은 행 개수를 유지합니다.

예를 들어 각 행에 해당 지역의 전체 매출을 붙이고 싶다면:

df["region_total"] = (    
    df.groupby("region")["sales"].transform("sum")
)
df["sales_ratio"] = df["sales"] / df["region_total"]

결과 일부:

region sales region_total sales_ratio
서울 100 550 0.182
서울 300 550 0.545
부산 200 700 0.286
부산 400 700 0.571
서울 150 550 0.273
부산 100 700 0.143

각 행의 매출이 해당 지역 전체 매출에서 차지하는 비율을 계산했습니다.

이 패턴은 그룹별 비율, 그룹 평균과의 차이, 그룹별 정규화 등을 할 때 많이 사용합니다.

예를 들어 지역 평균보다 매출이 높은 행만 추출할 수도 있습니다.

df[    
    df["sales"] >    df.groupby("region")["sales"].transform("mean")
]

6. 집계한 뒤 정렬하기

그룹별 집계 후 크기순으로 정렬하는 작업도 매우 흔합니다.

summary = (    
    df.groupby("region", as_index=False)      
        .agg(total_sales=("sales", "sum"))      
        .sort_values("total_sales", ascending=False)
)

결과:

region total_sales
부산 700
서울 550

sort_values()의 ascending=False는 내림차순이라는 의미입니다.

이 구조는 지역별 매출 순위, 상품별 판매량 순위, 사용자별 활동량 순위 등에 그대로 적용할 수 있습니다.

정리

패턴 주로 사용하는 상황
groupby().sum() 그룹별 합계
groupby(["A", "B"]) 여러 기준으로 그룹화
groupby().agg() 여러 집계값을 동시에 계산
groupby().size() 그룹별 데이터 개수
groupby().nunique() 그룹별 고유값 개수
groupby().transform() 그룹별 값을 원본 행에 적용
groupby() + sort_values() 그룹별 집계 결과의 순위 계산

가장 먼저 groupby + agg + as_index=False 조합을 익히는 것을 추천합니다.

result = (    
    df.groupby(["region", "category"], as_index=False)      
        .agg(          
            total_sales=("sales", "sum"),          
            avg_sales=("sales", "mean"),          
            order_count=("sales", "size")      
        )      
        .sort_values("total_sales", ascending=False)
)

이 패턴 하나만 익숙해져도 실무에서 자주 작성하는 요약 테이블을 상당 부분 만들 수 있습니다.

그다음 transform()을 익히면 단순 집계를 넘어 그룹별 평균 비교, 비율 계산, 그룹 내 상대적인 값 계산까지 자연스럽게 확장할 수 있습니다.

반응형