파이썬(Python) 판다스(Pandas) 라이브러리를 활용해 데이터 전처리를 수행하다 보면, 연속적인 수치로 이루어진 데이터를 특정 기준에 따라 그룹화하거나 범주형 변수로 변환해야 하는 상황을 자주 마주하게 됩니다. 예를 들어 비즈니스 환경에서 “매출액에 따라 고객을 고가/저가 구매자로 분류”하거나, “시험 점수를 기준으로 학점(A, B, C)을 부여”하고, “고객의 누적 이용 시간을 기준으로 균등한 비율의 5개 등급을 나누는” 작업 등이 이에 해당합니다.
연속형 데이터를 범주형 데이터로 변환하는 과정을 ‘이산화(Discretization)’ 또는 ‘구간화(Binning)’라고 부르며, 이는 데이터 분석의 가독성을 높이고 머신러닝 분류 모델의 예측 성능을 안정화하는 데 기여합니다. 이번 글에서는 조건별 데이터 분류의 핵심 도구인 넘파이의 np.where(), 판다스의 pd.cut(), pd.qcut()의 개념과 사용법을 체계적으로 정리해 보겠습니다.
1. 두 가지 조건 분기의 표준: np.where() 함수
np.where()는 판다스가 아닌 넘파이(NumPy) 라이브러리의 함수이지만, 판다스 데이터프레임의 열을 조건에 따라 이분법적으로 분류하여 파생변수를 생성할 때 널리 쓰이는 도구입니다. 엑셀의 IF 함수와 작동 원리가 유사합니다.
1.1. np.where()의 기본 문법과 비즈니스 예시
기본적인 사용 형식은 np.where(조건식, 참일_때의_값, 거짓일_때의_값) 입니다.
import pandas as pd
import numpy as np
# 가상의 이커머스 고객 데이터 생성
customer_df = pd.DataFrame({
'고객ID': ['C01', 'C02', 'C03', 'C04', 'C05'],
'나이': [24, 38, 19, 45, 31],
'구매금액': [120000, 450000, 80000, 950000, 300000]
})
# 구매금액이 300,000원 이상인 고객을 'VIP', 미만인 고객을 'General'로 분류
customer_df['고객등급'] = np.where(customer_df['구매금액'] >= 300000, 'VIP', 'General')
print(customer_df[['고객ID', '구매금액', '고객등급']])
1.2. 다중 조건 처리를 위한 np.where() 중첩
세 가지 이상의 조건으로 분류해야 할 때는 np.where() 내부에 다시 np.where()를 중첩하여 if-else if-else 구조를 구현할 수 있습니다. 다만, 조건이 너무 많아지면 코드의 가독성이 떨어질 수 있으므로 복잡한 다중 분기에는 뒤이어 소개할 pd.cut()이나 지난 16화에서 배운 apply() 함수를 고려하는 편이 좋습니다.
2. 지정한 수치 기준으로 구간 나누기: pd.cut() 함수
pd.cut() 함수는 데이터의 값 자체를 기준으로 삼아, 사용자가 직접 정의한 고정된 경계값(Bins)에 따라 데이터를 구간화하는 도구입니다.
2.1. pd.cut()의 핵심 파라미터 구조
- x: 구간화할 대상 시리즈 또는 배열을 지정합니다.
- bins: 구간을 나누는 기준을 정의합니다. bins에 정수를 입력하면 데이터의 최소값부터 최대값까지의 범위를 동일한 너비(Equal-width)로 나누어 구간을 생성합니다.
- labels: 각 구간에 부여할 이름(범주 레이블)을 리스트 형태로 지정합니다. 지정하지 않으면 구간의 수치 범위가 레이블로 출력됩니다.
- include_lowest:
True로 설정하면 가장 왼쪽 경계값(최솟값)을 포함하여 연산합니다.
2.2. 비즈니스 예시로 보는 pd.cut() 활용
고객의 나이 변수를 기준으로 ‘미성년/청년/중장년’ 범주형 파생변수를 가공해 보겠습니다.
# 구간 경계값 설정 (0~20세, 20~40세, 40~60세 구간)
bins_edges = [0, 20, 40, 60]
labels_names = ['미성년', '청년', '중장년']
# pd.cut을 활용한 나이 데이터 구간화
customer_df['연령대'] = pd.cut(
x=customer_df['나이'],
bins=bins_edges,
labels=labels_names,
include_lowest=True
)
print(customer_df[['고객ID', '나이', '연령대']])
연산 결과 ‘연령대’ 열은 판다스의 범주형 타입인 category 형태로 정돈됩니다. 수치 기준이 명확한 법정 연령 분류나 고정 단가 구간 분석에 유용합니다.
3. 데이터 분포 비율 기준으로 구간 나누기: pd.qcut() 함수
pd.qcut() 함수는 데이터의 절대적인 값이 아니라 분위수(Quantile)를 기준으로 데이터를 분할하여, 각 구간에 포함되는 데이터 개수가 가능한 한 동일하도록 구간을 생성하는 도구입니다.
3.1. pd.qcut()의 특징과 비즈니스 활용
예를 들어 특정 쇼핑몰에 가입한 고객들의 구매 금액 분포가 일부 상위 고객에게 극단적으로 쏠려 있다면, pd.cut()으로 구간을 나눴을 때 특정 구간에만 데이터가 밀집하고 나머지 구간은 텅 빌 수 있습니다. 이때 pd.qcut()을 사용하면 데이터 개수를 기준으로 백분위수를 계산하여 등급을 나눌 수 있습니다.
# 구매금액을 기준으로 데이터 개수가 균등하게 3개 등급(상/중/하)으로 분할
# q=3은 33.3%, 66.6%, 100% 지점을 기준으로 분할함을 의미합니다.
customer_df['구매수준'] = pd.qcut(
x=customer_df['구매금액'],
q=3,
labels=['하', '중', '상']
)
print(customer_df[['고객ID', '구매금액', '구매수준']])
pd.qcut() 연산을 거치면 ‘상’, ‘중’, ‘하’ 각 등급에 배정되는 고객의 수가 균일하게 배분되므로, 상대 평가 기반의 고객 티어링 시스템이나 표본 분포 균등화 작업에 적절히 부합합니다.
4. 세 가지 분류 도구의 핵심 차이점 비교 요약
각 함수의 용도와 분류 메커니즘을 요약하면 다음과 같은 가이드라인을 세울 수 있습니다.
| 함수명 | 분류 기준 | 주요 반환 타입 | 권장 시나리오 |
np.where() | 단일 논리 조건식의 참/거짓 | 조건에 지정한 데이터 타입 | 두 가지 상태로의 이분법적 분류 및 파생변수 생성 |
pd.cut() | 값의 크기 기준 (지정한 수치 너비) | 범주형 (category) | 연령대, 금액 구간 등 절대적인 기준선 분류 |
pd.qcut() | 데이터 개수 기준 (분위수 비율) | 범주형 (category) | 상대 평가 등급 부여, 균등 표본 분할 |
5. 빅데이터분석기사 실기 시험 환경에서의 실전 활용 포인트
빅데이터분석기사 실기 시험(특히 작업형 제1유형)에서는 연속형 변수를 구간화(Binning) 한 후 조건에 맞는 샘플들의 빈도나 통계량을 산출하라는 복합 문항이 출제됩니다.
5.1. pd.cut() 기반 그룹 빈도 분석 및 통계량 추출
예를 들어 “주어진 데이터셋의 특정 수치 변수를 최소값부터 최대값까지 너비가 균등한 5개의 구간으로 분할한 후, 가장 데이터가 많이 포함된 구간에 속한 샘플들의 나이 평균을 구하시오”라는 요건이 나온다면 다음과 같이 대응할 수 있습니다.
# [시험장 실전 대응 프로토콜]
# 1. bins에 정수 5를 대입하여 균등 너비 구간 컬럼 생성 (labels 생략 시 구간 범위가 레이블이 됨)
df['구간'] = pd.cut(df['수치변수'], bins=5)
# 2. value_counts()를 사용하여 가장 빈도가 높은 최빈 구간 명칭 식별
top_interval = df['구간'].value_counts().index[0]
# 3. 불리언 인덱싱으로 해당 구간의 행만 필터링하여 나이 평균 연산
result = df.loc[df['구간'] == top_interval, '나이'].mean()
print(result)
이처럼 연속형 데이터를 유연하게 범주형 신호로 정제하고 결합하는 역량은 탐색적 데이터 분석(EDA)과 피처 엔지니어링 단계에서 유용한 밑바탕이 됩니다.
6. 요약 및 다음 화 안내
np.where(): 엑셀의 IF문처럼 이분법적인 조건 분기를 수행하여 신속하게 파생 피처를 생성하도록 지원합니다.pd.cut(): 데이터의 절대적인 수치 경계선을 기반으로 구간을 나누며 법정 연령대 등의 분류에 적절합니다.pd.qcut(): 데이터의 상대적인 빈도 분포(분위수)를 기준으로 삼아 표본의 개수가 균등하게 쪼개지도록 분할합니다.
다음 [판다스 23화]에서는 대규모 모집단 데이터에서 표본을 무작위로 추출하여 가설 검정이나 모델 검증의 객관성을 확보하기 위한 sample 함수로 랜덤 샘플링과 데이터 추출하기에 대해 상세히 학습해 보겠습니다. 데이터 표본 추출 기술을 함께 마스터해 봅시다.