Pandas 데이터 변환 정리: 구간화(Binning)와 정규화·표준화

Alchemist·2026년 9월 22일

KT AIVLE

목록 보기
10/40

데이터 전처리에서 중요한 작업 중 하나가 변수의 표현 방식을 분석 목적에 맞게 바꾸는 것이다.

원본 데이터가 그대로도 의미가 있을 수 있지만, 분석이나 머신러닝에 바로 사용하기에는 지나치게 세밀하거나 변수마다 값의 범위가 너무 다를 때가 있다.

예를 들어 웹 서비스 데이터를 생각해보면 다음과 같은 문제가 생길 수 있다.

응답 시간(ms): 80 ~ 3,000
요청 크기(KB): 1 ~ 500
재시도 횟수:   0 ~ 5

이 값들을 그대로 비교하면 단위와 범위가 서로 다르기 때문에 해석이나 모델 학습에서 특정 변수가 지나치게 큰 영향을 줄 수 있다.

또 사용자 활동량처럼 연속형 값을 그대로 보는 것보다 낮음, 보통, 높음처럼 묶는 것이 더 이해하기 쉬운 경우도 있다.

이럴 때 사용할 수 있는 대표적인 데이터 변환 방법이 구간화(Binning) 와 스케일링(Scaling) 이다.

원본 연속형 데이터
    ↓
목적에 맞는 변환
    ├─ 구간화 → 범주형 정보로 단순화
    └─ 스케일링 → 값의 범위를 조정

이번 글에서는 Pandas와 scikit-learn을 이용해 구간화와 Min-Max Scaling, Z-Score 기반 표준화를 정리한다.


데이터 변환은 왜 필요한가?

데이터 변환은 원본 값을 무조건 바꾸는 작업이 아니라 분석 목적에 더 잘 맞는 형태로 표현을 바꾸는 과정이다.

대표적인 목적은 다음과 같다.

  • 연속형 값을 범주형 값으로 바꿔 특징을 쉽게 파악하기
  • 변수별 값의 범위 차이를 줄이기
  • 거리 기반 머신러닝 알고리즘에서 변수 영향력의 차이를 완화하기
  • 데이터 위치나 분포를 상대적인 기준으로 해석하기

같은 숫자라도 문제에 따라 의미가 다르기 때문에 변환 기준은 항상 목적과 도메인 지식을 함께 고려해야 한다.


1. 구간화(Binning)

구간화는 연속형 데이터를 일정한 범위로 나누고 각 구간에 범주를 부여하는 방법이다.

예를 들어 API 호출 횟수가 다음과 같다고 하자.

12, 35, 80, 120, 310, 760

이를 그대로 사용하는 대신 다음처럼 단순화할 수 있다.

0 ~ 100      → low
100 ~ 500    → medium
500 이상     → high

이렇게 하면 숫자 하나하나를 비교하는 대신 사용량 수준이라는 새로운 의미를 가진 변수를 만들 수 있다.


구간화에서 먼저 결정해야 할 것

구간화는 크게 두 가지 방식으로 접근할 수 있다.

방식기준Pandas
구간 범위 직접 지정사용자가 경계값을 직접 정함pd.cut()
분포 기반 분할각 구간에 비슷한 수의 데이터를 배치pd.qcut()

둘 중 어떤 방식이 더 좋다고 단정할 수는 없다.

서비스 정책처럼 명확한 기준이 있다면 cut()이 자연스럽고, 데이터의 상대적인 순위를 기준으로 비슷한 크기의 그룹을 만들고 싶다면 qcut()이 유용하다.


2. pd.cut()으로 원하는 기준 직접 만들기

웹 서비스의 일일 요청 수를 기준으로 사용량을 분류한다고 가정해보자.

import numpy as np
import pandas as pd

df = pd.DataFrame({
    "request_count": [72, 95, 130, 250, 480, 650, 780]
})

구간 경계를 직접 지정한다.

bins = [0, 100, 500, np.inf]
labels = ["low", "medium", "high"]

df["usage_level"] = pd.cut(
    df["request_count"],
    bins=bins,
    labels=labels
)

결과를 확인한다.

print(df)

핵심은 구간의 숫자 자체보다 왜 그 경계를 선택했는지다.

예를 들어 실제 서비스라면 다음과 같은 기준을 사용할 수 있다.

  • 무료 요금제 사용 한도
  • 트래픽 경고 기준
  • 사용자 활동 등급
  • 운영팀이 사용하는 모니터링 기준

즉, pd.cut()은 비즈니스나 도메인에서 이미 의미가 있는 경계값을 표현하기 좋다.


직접 실행한 구간화 결과에서 확인한 점

80개 관측값을 세 구간으로 나누는 실습에서는 다음 경계를 사용했다.

bins = [0, 100, 500, max_value]

세 범주로 나눈 결과는 다음과 같았다.

medium    73
low        5
high       2

데이터 대부분이 medium에 몰려 있고 high는 2개뿐이었다.

이 결과는 cut()의 중요한 특징을 보여준다.

구간의 폭을 사용자가 정한다고 해서 각 구간에 데이터가 비슷한 개수로 들어가는 것은 아니다.


3. pd.qcut()으로 분포 기준 구간 만들기

각 그룹에 가능한 한 비슷한 개수의 데이터를 넣고 싶다면 qcut()을 사용할 수 있다.

labels = ["low", "medium", "high"]

df["usage_level_q"] = pd.qcut(
    df["request_count"],
    q=3,
    labels=labels
)

q=3은 데이터를 분위수 기준으로 세 그룹으로 나누겠다는 뜻이다.

개념적으로는 다음과 같다.

전체 데이터 정렬
    ↓
관측값 개수가 비슷하도록 분할
    ↓
low / medium / high

실제 실행 결과

80개 데이터를 세 구간으로 나눈 결과는 다음과 같았다.

low       29
medium    26
high      25

cut() 결과와 비교하면 차이가 분명하다.

방식lowmediumhigh
직접 경계 지정5732
분포 기반 구간화292625

qcut()은 값의 간격보다 데이터 개수의 균형을 더 중요하게 본다.


qcut()에서 주의할 점

데이터에 같은 값이 지나치게 많이 반복되면 분위수 경계를 만들기 어려울 수 있다.

예를 들어 다음 데이터가 있다고 하자.

1, 1, 1, 1, 1, 3, 8, 10

동일한 값이 여러 개 몰려 있으므로 원하는 개수의 구간으로 정확히 분리하기 어려울 수 있다.

이런 경우에는 다음 방법을 검토할 수 있다.

  • pd.cut()으로 도메인 기준 구간 사용
  • 구간 개수 줄이기
  • 중복 경계 처리 여부 검토
  • 데이터 분포 자체를 먼저 확인

구간화는 단순한 함수 호출보다 데이터 분포를 먼저 보는 것이 중요하다.


4. 정규화와 표준화가 필요한 이유

구간화가 값을 범주로 바꾸는 작업이라면, 스케일링은 연속형 값을 유지하면서 값의 크기 범위를 조정하는 작업이다.

예를 들어 머신러닝 입력 변수가 다음과 같다고 하자.

page_view       1 ~ 100
session_time    10 ~ 10,000
purchase_count  0 ~ 8

숫자 크기만 보면 session_time이 훨씬 크다.

특히 거리(distance)를 사용하는 알고리즘에서는 이런 차이가 결과에 영향을 줄 수 있다.

대표적으로 K-Means는 관측값 사이의 거리를 기반으로 비슷한 데이터를 묶는다.

서로 다른 변수 범위
    ↓
거리 계산에서 특정 변수 영향이 커질 수 있음
    ↓
스케일 조정
    ↓
변수 간 비교 가능한 수준으로 맞춤

5. Min-Max Scaling

Min-Max Scaling은 데이터의 최솟값을 0, 최댓값을 1로 맞추고 나머지 값을 그 사이에 배치한다.

공식은 다음과 같다.

x_scaled = (x - min) / (max - min)

scikit-learn에서는 MinMaxScaler를 사용할 수 있다.

from sklearn.preprocessing import MinMaxScaler

scaler = MinMaxScaler()

df["scaled_value"] = scaler.fit_transform(
    df[["request_count"]]
)

변환 후 확인한다.

print(df[["request_count", "scaled_value"]])

무엇을 확인해야 할까?

describe()로 범위를 확인하면 된다.

df["scaled_value"].describe()

정상적으로 변환되었다면 기본 설정에서는 다음 특징을 가진다.

min → 0
max → 1

직접 실행한 결과

80개 데이터에 Min-Max Scaling을 적용했을 때 실제로 다음 범위를 확인했다.

원본 최소값: 5
원본 최대값: 780

변환 후 최소값: 0.0
변환 후 최대값: 1.0

또 원본 값 650은 약 0.832258로 변환되었다.

즉, Min-Max Scaling은 원래 값 자체보다 전체 범위 안에서 어느 위치에 있는 값인지 보기 쉽게 만든다.


6. Z-Score 기반 표준화

Z-Score 방식은 각 값이 평균에서 표준편차 몇 배만큼 떨어져 있는지를 나타낸다.

z = (x - 평균) / 표준편차

scikit-learn에서는 StandardScaler를 사용한다.

from sklearn.preprocessing import StandardScaler

std_scaler = StandardScaler()

df["standardized_value"] = std_scaler.fit_transform(
    df[["request_count"]]
)

이 방식은 데이터를 평균 0을 중심으로 재배치하고 표준편차를 기준으로 스케일을 조정한다.

용어는 자료나 라이브러리 문맥에 따라 조금씩 다르게 쓰인다. 실무에서는 StandardScaler를 보통 표준화(Standardization) 라고 부르고, Min-Max Scaling과 함께 넓은 의미의 스케일링 방법으로 다루는 경우가 많다.


직접 실행한 결과에서 확인한 점

실습 데이터에 StandardScaler를 적용한 결과 전체 평균은 거의 0에 가까워졌다.

mean ≈ 0

또 최대값에 해당하는 관측치는 약 다음 값으로 변환되었다.

max z-score ≈ 6.640282

중간에 있던 큰 값 하나는 다음과 같이 확인되었다.

원본 값: 650
표준화 값: 약 5.265510

이처럼 표준화된 값은 평균에서 얼마나 멀리 떨어져 있는지 해석하기 좋다.


7. Min-Max Scaling과 StandardScaler 비교

두 방식은 모두 변수의 스케일을 조정하지만 해석 방식이 다르다.

구분Min-Max ScalingZ-Score 표준화
대표 클래스MinMaxScalerStandardScaler
중심 개념최소~최대 범위 내 위치평균으로부터의 거리
기본 범위보통 0~1고정된 상·하한 없음
변환 후 중심데이터에 따라 다름평균이 0에 가까움
극단값 영향범위를 크게 늘릴 수 있음평균·표준편차에도 영향
활용 관점정해진 범위로 맞추고 싶을 때서로 다른 단위의 변수를 비교할 때

어느 방식이 항상 더 좋은 것은 아니다.

데이터 분포와 사용할 알고리즘에 따라 선택해야 한다.


8. 이상치가 있는 상태에서 Scaling하면 생기는 일

실습 데이터에는 최댓값이 780인 큰 값이 포함되어 있었다.

원본 통계는 다음과 같았다.

count     80
mean      152.0875
std        95.1577
min         5
median    141
max       780

Min-Max Scaling을 적용하면 이 최댓값이 1이 되고 나머지 값들은 0~1 사이에 압축된다.

StandardScaler를 적용하면 이 값의 Z-Score가 약 6.64가 된다.

이 결과에서 기억할 점은 다음과 같다.

스케일링은 이상치를 제거하는 작업이 아니다.

이상치 포함 데이터
    ↓
Scaling
    ↓
이상치가 사라지는 것이 아니라
변환된 공간에서도 영향이 남음

따라서 머신러닝용 전처리에서는 필요하다면 이상치 처리 여부를 먼저 검토한 뒤 스케일링을 적용해야 한다.


9. fit()과 transform()을 분리해서 이해하기

scikit-learn의 Scaler를 처음 사용할 때는 fit_transform()만 외우기 쉽다.

하지만 실제 모델링에서는 둘의 역할을 구분해서 이해하는 것이 중요하다.

scaler.fit(train_df[["request_count"]])

train_scaled = scaler.transform(
    train_df[["request_count"]]
)

test_scaled = scaler.transform(
    test_df[["request_count"]]
)

개념적으로는 다음과 같다.

fit
→ 변환에 필요한 기준값 학습
  (min, max, mean, std 등)

transform
→ 학습한 기준으로 실제 데이터 변환

훈련 데이터와 테스트 데이터에 각각 따로 fit()하면 데이터 누수로 이어질 수 있다.

따라서 머신러닝에서는 훈련 데이터로 기준을 학습하고, 테스트 데이터에는 동일한 기준으로 transform만 수행하는 패턴을 기억하는 것이 좋다.


10. 구간화와 스케일링은 목적이 다르다

둘 다 데이터 변환이지만 결과의 의미는 완전히 다르다.

구분구간화스케일링
입력연속형 값연속형 값
출력범주형 값연속형 값
목적의미 있는 그룹으로 단순화값의 범위 조정
대표 함수cut, qcutMinMaxScaler, StandardScaler
예시트래픽을 low/medium/high로 분류요청 수를 0~1 범위로 변환

구간화는 정보의 세밀함을 일부 포기하는 대신 해석이 쉬워지고, 스케일링은 원래의 순서 관계를 유지하면서 값의 표현 범위를 바꾼다.


개발자 관점에서 이해하기

웹 서비스의 사용자 데이터를 예로 들어보자.

다음과 같은 특성이 있다고 가정한다.

login_count
session_minutes
purchase_amount
api_request_count

구간화가 유용한 경우

사용자 활동 등급을 만들고 싶다면:

api_request_count
    ↓
low / medium / high

이 결과는 리포트, 대시보드, 운영 기준처럼 사람이 읽는 영역에서 활용하기 쉽다.

스케일링이 유용한 경우

여러 수치형 변수를 머신러닝 입력으로 사용한다면:

login_count        0 ~ 30
session_minutes    1 ~ 5,000
purchase_amount    0 ~ 3,000,000

그대로 거리 기반 모델에 넣기보다 스케일을 조정하는 것이 중요할 수 있다.

결국 변환 방법은 다음 질문에서 출발하면 된다.

이 값을 사람이 해석하기 쉽게 묶고 싶은가?
→ 구간화

수치 정보는 유지하면서 변수 범위를 맞추고 싶은가?
→ 스케일링

실습에서 확인할 체크포인트

데이터 변환 코드를 실행한 뒤에는 변환 자체가 성공했는지만 보지 말고 결과의 의미도 확인해야 한다.

  1. 구간화 후 각 범주의 개수 확인

    df["category"].value_counts()
  2. 경계 근처 값이 의도한 범주에 들어갔는지 확인

    df[["value", "category"]].head()
  3. Min-Max Scaling 후 최솟값과 최댓값 확인

    df["scaled_value"].describe()
  4. StandardScaler 후 평균이 0에 가까운지 확인

    df["standardized_value"].mean()
  5. 극단값이 변환 결과에 어떤 영향을 주는지 확인

  6. 머신러닝에서는 train 데이터만으로 Scaler를 fit했는지 확인


핵심 정리

  • 데이터 변환은 분석 목적에 맞게 데이터 표현 방식을 바꾸는 전처리 과정이다.
  • 구간화(Binning) 는 연속형 데이터를 범주형 값으로 바꾼다.
  • pd.cut()은 사용자가 직접 구간 경계를 정할 때 사용한다.
  • pd.qcut()은 관측값 개수가 비슷하도록 분위수 기준으로 구간을 나눈다.
  • 같은 값이 지나치게 많이 반복되면 qcut()이 원하는 구간을 만들기 어려울 수 있다.
  • Min-Max Scaling은 값을 기본적으로 0~1 범위로 변환한다.
  • StandardScaler는 평균을 0 중심으로 맞추고 표준편차를 기준으로 값을 조정한다.
  • 스케일링은 이상치를 제거하지 않기 때문에 극단값이 있다면 별도로 확인해야 한다.
  • 거리 기반 알고리즘에서는 변수별 스케일 차이가 결과에 영향을 줄 수 있다.
  • 머신러닝에서는 훈련 데이터로만 Scaler를 fit()하고 테스트 데이터에는 transform()만 적용하는 것이 중요하다.

정리하며

구간화와 스케일링은 모두 데이터를 바꾸는 작업이지만 목적은 다르다.

구간화는 수치형 데이터를 의미 있는 그룹으로 단순화하는 데 초점이 있고, 스케일링은 수치 정보 자체는 유지하면서 변수 사이의 크기 차이를 조정하는 데 초점이 있다.

중요한 것은 함수를 외우는 것보다 왜 변환하는지 먼저 정의하는 것이다.

분석 목적 확인
    ↓
데이터 분포 확인
    ↓
구간화 또는 스케일링 선택
    ↓
변환 결과 검증
    ↓
분석 / 모델링 적용

전처리에서 데이터 변환은 단순한 형식 변경이 아니라 이후 분석과 모델이 데이터를 바라보는 기준을 만드는 과정이라고 볼 수 있다.

#Python #Pandas #DataPreprocessing #데이터전처리 #데이터변환 #Binning #구간화 #Normalization #Standardization #ScikitLearn #MachineLearning #DataScience

profile
html_programming_language

0개의 댓글