[판다스 18화] pivot_table과 crosstab으로 데이터 요약하기 | Python Pandas | 빅분기, 빅데이터분석기사 실기

파이썬(Python) 판다스(Pandas) 라이브러리를 활용해 데이터를 다루다 보면, 17화에서 다룬 groupby() 연산 결과보다 더 입체적이고 다각적인 형태로 데이터를 요약해야 하는 상황을 마주하게 됩니다. 예를 들어 비즈니스 환경에서 “연도별/월별 매출 현황판”을 만들거나, “성별에 따른 연령대별 구매 빈도수 교차표”를 작성하는 작업 등이 이에 해당합니다.

판다스에서 이처럼 행과 열을 격자 구조로 배치하여 2차원 요약 테이블을 생성하는 대표적인 함수가 바로 pivot_table()crosstab()입니다. 두 함수는 요약 통계와 데이터 시각화 직전 단계에서 유용하게 활용되며, 빅데이터분석기사(빅분기) 실기 시험에서도 데이터 추출 및 가공 변별력을 평가하는 단골 요소입니다. 이번 글에서는 두 함수의 핵심 사용법과 비즈니스 활용 예시, 그리고 실무 적용 시의 유의점을 체계적으로 정리해 보겠습니다.

1. 엑셀 피벗 테이블의 강력함을 파이썬으로: pivot_table()

pivot_table() 함수는 이름 그대로 엑셀(Excel)의 피벗 테이블 기능을 코드 한 줄로 구현할 수 있도록 설계된 도구입니다. 대량의 행(Row) 데이터를 인덱스(행)와 컬럼(열) 기준으로 그룹화하고, 특정 수치형 변수의 요약 통계량을 그리드 형태로 시각화해 줍니다.

1.1. pivot_table()의 핵심 파라미터 구조

  • index: 행 방향(세로축)에 배치할 기준 컬럼명을 지정합니다.
  • columns: 열 방향(가로축)에 배치할 기준 컬럼명을 지정합니다.
  • values: 요약 통계량을 계산할 대상 수치형 컬럼명을 지정합니다.
  • aggfunc: 데이터 집계 시 사용할 함수를 정의합니다. 기본값은 평균을 구하는 'mean'이며, 필요에 따라 'sum', 'count', 'max', 'min' 등을 지정할 수 있습니다.
  • margins: True로 설정하면 행과 열의 전체 집계 결과(All) 레이블이 우측과 하단에 자동으로 추가됩니다.

1.2. 비즈니스 예시로 이해하는 pivot_table 활용

가상의 이커머스 채널별 매출 데이터를 생성하여 매장 유형과 결제 수단에 따른 매출액 평균 현황판을 만들어 보겠습니다.

import pandas as pd

# 가상 매장 거래 데이터 생성
sales_df = pd.DataFrame({
    '매장유형': ['온라인', '오프라인', '온라인', '오프라인', '온라인', '오프라인'],
    '결제수단': ['신용카드', '신용카드', '간편결제', '간편결제', '신용카드', '간편결제'],
    '구매건수': [3, 1, 5, 2, 2, 4],
    '매출액': [150000, 45000, 250000, 80000, 90000, 160000]
})

# 매장유형(행)과 결제수단(열)에 따른 매출액 평균 집계
pivot_result = sales_df.pivot_table(
    index='매장유형',
    columns='결제수단',
    values='매출액',
    aggfunc='mean',
    margins=True
)
print(pivot_result)

[출력 결과]

결제수단         간편결제      신용카드            All
매장유형                                      
오프라인     120000.0   45000.0   95000.000000
온라인      250000.0  120000.0  163333.333333
All      163333.3  95000.0   129166.666667

출력된 표를 통해 오프라인 매장의 간편결제 평균 매출(120,000원)과 신용카드 평균 매출(45,000원)의 격차를 평면 구조에서 한눈에 비교할 수 있습니다. margins=True 옵션에 의해 전체 평균 지표인 All 영역도 함께 출력된 것을 확인할 수 있습니다.

2. 범주형 데이터의 빈도수 교차 분석: crosstab()

pivot_table()이 주로 특정 수치형 데이터의 통계량을 요약한다면, crosstab() 함수는 범주형(Categorical) 변수 간의 빈도수(Frequency, 개수)나 상대적 비율을 파악하는 교차표(Contingency Table)를 생성할 때 유용합니다.

2.1. crosstab()의 특징과 기본 문법

crosstab()은 데이터프레임의 메서드가 아닌 판다스 라이브러리의 독립 함수이므로 pd.crosstab() 형태로 호출해야 합니다. 첫 번째 인자에는 행으로 배치할 시리즈 객체를, 두 번째 인자에는 열로 배치할 시리즈 객체를 전달합니다.

# 매장 유형과 결제 수단 간의 빈도수(거래 건수) 교차표 생성
cross_result = pd.crosstab(index=sales_df['매장유형'], columns=sales_df['결제수단'])
print(cross_result)

[출력 결과]

결제수단  간편결제  신용카드
매장유형            
오프라인     2     1
온라인      1     2

별도의 수치 지정 없이도 각 범주 조합에 해당하는 행 데이터의 빈도(Count)가 자동으로 매핑됩니다.

2.2. 빈도수를 넘어 비율 분포 확인하기 (normalize)

실무에서는 단순 빈도수보다 각 행이나 열에서 해당 범주가 차지하는 백분율(비율) 분포를 구해야 할 때가 많습니다. 이때는 normalize 파라미터를 활용합니다.

  • normalize='index': 각 행(가로축)의 합이 1.0(100%)이 되도록 비율을 계산합니다.
  • normalize='columns': 각 열(세로축)의 합이 1.0이 되도록 비율을 계산합니다.
  • normalize='all': 데이터프레임 전체 원소의 합이 1.0이 되도록 비율을 계산합니다.

Python

# 매장유형별 결제수단의 선택 비율 분포 계산 (행 기준 정규화)
normalized_cross = pd.crosstab(
    index=sales_df['매장유형'], 
    columns=sales_df['결제수단'], 
    normalize='index'
)

3. 두 요약 함수의 핵심 차이점과 적절한 선택 기준

두 함수 모두 최종적으로 가로와 세로 축을 지닌 2차원 표 형태의 결과를 도출하지만, 구조적 특성과 주된 활용 영역에는 다음과 같은 차이가 존재합니다.

비교 항목pivot_table() 함수crosstab() 함수
호출 방식DataFrame 객체의 메서드 (df.pivot_table())Pandas 라이브러리의 독립 함수 (pd.crosstab())
주요 데이터 유형수치형(Continuous) 데이터의 집계 연산범주형(Categorical) 데이터의 빈도 분석
디폴트 작동 방식특정 수치형 컬럼의 평균(mean) 자동 산출조건에 만족하는 데이터의 개수(count) 산출
인자 입력 형태컬럼명을 문자열 또는 리스트로 전달시리즈(Series) 객체 자체를 직접 전달

따라서 가공하려는 원본 데이터의 특성에 맞춰 기준을 세우는 편이 효율적입니다.

  • 데이터프레임 내부에 존재하는 여러 수치 피처들의 사칙 연산 통계가 목적이라면 pivot_table을 선택합니다.
  • 단순 두 범주형 독립변수 집단 간의 빈도 밀도나 설문조사 결과의 교차 빈도 비율 분포를 정제할 때는 crosstab을 우선적으로 고려합니다.

4. 실무 환경에서의 데이터 변환 유의사항 및 결측치 제어

4.1. 결과 테이블의 Multiindex 처

pivot_table이나 crosstab 연산을 수행하고 나면 지정한 인덱스와 컬럼이 데이터프레임의 행 인덱스 및 컬럼 인덱스로 설정됩니다. 이를 다른 전처리 단계와 연계하기 위해 일반 평면 테이블로 복구해야 한다면 구조 변경 작업을 수반해야 합니다.

# pivot_table 결과의 행 인덱스를 컬럼으로 내리고 구조 다듬기
flattened_df = pivot_result.reset_index()

# 컬럼에 남아있는 빈 상위 축(결제수단) 명칭 흔적 제거
flattened_df.columns.name = None

4.2. 빈 격차 영역의 결측치 처리 (fill_value)

특정 행과 열 범주의 조합에 해당하는 데이터가 원본 데이터셋에 단 한 건도 존재하지 않는 상황이 발생할 수 있습니다. 이때 판다스는 해당 격자 칸을 NaN(결측치)으로 비워두게 됩니다. 이후 머신러닝 피처 등으로 사용할 때 결측치 에러를 방지하고 싶다면 fill_value=0 파라미터를 지정하여 빈칸을 안전하게 0 등의 상수로 메우는 방식을 권장합니다.

# 빈 조합 영역을 NaN 대신 0으로 채워 그리드 구성
safe_pivot = sales_df.pivot_table(
    index='매장유형', 
    columns='결제수단', 
    values='매출액', 
    fill_value=0
)

5. 빅데이터분석기사 실기 시험 환경에서의 실전 활용 포인트

빅데이터분석기사 실기(특히 작업형 제1유형)에서는 2차원 교차 요약표의 특정 위치 값을 추출하거나 연산하는 조건부 문제가 종종 출제됩니다.

5.1. 교차 요약 결과 기반의 특정 원소 추출

예를 들어 “고객 데이터셋에서 거주지역별(행) 및 가입등급별(열) 총 구매금액의 평균을 계산한 뒤, ‘서울’ 지역의 ‘Gold’ 등급에 해당하는 매출액 값을 구하시오”라는 문제가 있다면 아래와 같은 단계로 코드를 구성할 수 있습니다.

# 1. pivot_table 함수로 조건에 맞는 요약표 생성
summary_table = df.pivot_table(
    index='거주지역', 
    columns='가입등급', 
    values='구매금액', 
    aggfunc='mean', 
    fill_value=0
)

# 2. 명칭 기반 loc 속성을 활용하여 특정 교차 지점의 원소 추출
result = summary_table.loc['서울', 'Gold']
print(result)

5.2. groupby()와의 유연한 교체 능력 확보

많은 수험생들이 2차원 요약 문제를 마주했을 때 pivot_table만 고집하다 파라미터 구조가 혼동되어 실수를 유발하곤 합니다. pivot_table의 대부분의 집계 결과는 groupby().agg()와 unstack() 등을 조합하여 구현할 수도 있습니다.

따라서 시험장 환경에서는 본인에게 가장 익숙하고 오타 확률이 낮은 함수를 유연하게 선택하는 전략이 제한된 시간 내에 안정적으로 정답을 확보하는 지름길이 됩니다.

6. 요약 및 다음 화 안내

  • pivot_table(): 엑셀의 피벗 테이블처럼 인덱스와 컬럼을 축으로 수치형 데이터를 요약 통계량(디폴트 평균)으로 집계해 줍니다.
  • pd.crosstab(): 독립 함수 형태로 구동되며, 두 범주형 변수의 발생 빈도수와 상대적 백분율 분포 비율을 파악하는 교차 분석에 최적화되어 있습니다.
  • 예외 관리: 데이터 공백에 따른 에러를 막기 위해 fill_value=0 파라미터를 활용하고, 연산 이후 구조 정상화를 위해 reset_index() 적용을 고려할 수 있습니다.

다음 [판다스 19화]에서는 서로 다른 출처에서 분산 수집된 복수의 데이터프레임들을 공통 키값을 기준으로 정밀하게 병합하고 조립하는 기법인 merge, join, concat 차이점과 데이터 병합 방법에 대해 상세히 학습해 보겠습니다. 데이터 통합 단계의 핵심 역량을 함께 길러봅시다.

댓글 남기기