데이터 전처리 및 변수 생성
From the 데이터 사이언스 curriculum
TL;DR
데이터 전처리는 원시 데이터를 분석에 적합한 형태로 가공하는 필수 단계이며, 여기에는 결측치 처리, 이상치 제거, 데이터 스케일링 등이 포함됩니다. 변수 생성은 기존 변수들을 활용해 새로운 정보를 담은 변수를 만드는 과정으로, 모델의 예측 성능을 크게 향상시킬 수 있습니다. 이 두 과정은 데이터 분석 프로젝트의 성공을 좌우하는 핵심 요소입니다.
1. The Mental Model
데이터 전처리 및 변수 생성은 마치 요리사가 신선한 재료를 손질하고 양념을 하는 것과 같아요. 좋은 재료(원시 데이터)가 있어도 제대로 다듬고(전처리) 적절히 양념(변수 생성)하지 않으면 맛있는 요리(모델 성능)를 만들 수 없죠.
2. The Core Material
데이터 과학 프로젝트에서 모델링에 앞서 데이터 전처리 및 변수 생성은 전체 시간의 70% 이상을 차지할 정도로 중요합니다. 이 과정을 통해 데이터의 품질을 높이고, 모델이 더 잘 학습할 수 있도록 정보를 구조화합니다.
2.1 결측치 처리 (Missing Value Imputation)

Photo by Brett Jordan on Pexels
데이터에 값이 없는 경우가 많아요. 이를 NaN (Not a Number)으로 표시하기도 합니다. 결측치를 처리하는 방법은 다양하며, 데이터의 특성과 결측의 원인을 고려해야 합니다.
- 삭제 (Deletion): 결측치가 있는 행 또는 열을 단순히 제거합니다. 데이터 손실이 크지 않을 때 고려할 수 있습니다.
- 대체 (Imputation):
- 평균/중앙값/최빈값 대체: 수치형 변수에는 평균이나 중앙값을, 범주형 변수에는 최빈값을 사용합니다.
- 고정값 대체: 특정 의미 있는 값(예: 0, -1)으로 채웁니다.
- 예측 모델 활용: 다른 변수들을 이용해 결측값을 예측하여 채웁니다. (예: KNN Imputer, MICE)
import pandas as pd
import numpy as np
# 예시 데이터 생성
data = {'A': [1, 2, np.nan, 4, 5],
'B': [np.nan, 20, 30, 40, 50],
'C': ['X', 'Y', 'Z', np.nan, 'X']}
df = pd.DataFrame(data)
print("원본 DataFrame:\n", df)
# A열 결측치를 평균으로 대체
df['A'] = df['A'].fillna(df['A'].mean())
# B열 결측치를 0으로 대체
df['B'] = df['B'].fillna(0)
# C열 결측치를 최빈값으로 대체
df['C'] = df['C'].fillna(df['C'].mode()[0])
print("\n결측치 처리 후 DataFrame:\n", df)
2.2 이상치 처리 (Outlier Handling)

Photo by Kampus Production on Pexels
이상치는 대부분의 데이터와 동떨어진 값을 말하며, 모델 성능에 부정적인 영향을 줄 수 있습니다.
- 삭제: 이상치 데이터를 제거합니다. 데이터 양이 충분할 때 고려합니다.
- 변환: 로그 변환 등으로 데이터 분포를 변경하여 이상치의 영향을 줄입니다.
- 캡핑 (Capping): 이상치를 특정 최댓값/최솟값으로 제한합니다. (예: IQR(Interquartile Range) 기반)
2.3 데이터 스케일링 (Data Scaling)

Photo by Pixabay on Pexels
서로 다른 범위의 변수들을 동일한 척도로 맞춰주는 과정입니다. 특히 거리 기반 알고리즘(KNN, SVM 등)이나 경사하강법 기반 알고리즘(선형 회귀, 신경망)에서 중요합니다.
- Min-Max Scaling (정규화): 데이터를 0과 1 사이의 값으로 변환합니다.
$X_{normalized} = \frac{X - X_{min}}{X_{max} - X_{min}}$ - Standard Scaling (표준화): 데이터를 평균이 0, 표준편차가 1인 분포로 변환합니다.
$X_{standardized} = \frac{X - \mu}{\sigma}$
from sklearn.preprocessing import MinMaxScaler, StandardScaler
data = np.array([[10, 100], [20, 150], [30, 10]])
df_scale = pd.DataFrame(data, columns=['Age', 'Salary'])
print("\n스케일링 전 DataFrame:\n", df_scale)
# Min-Max 스케일링
scaler_mm = MinMaxScaler()
df_scaled_mm = scaler_mm.fit_transform(df_scale)
print("\nMin-Max 스케일링 후:\n", df_scaled_mm)
# Standard 스케일링
scaler_std = StandardScaler()
df_scaled_std = scaler_std.fit_transform(df_scale)
print("\nStandard 스케일링 후:\n", df_scaled_std)
2.4 변수 생성 (Feature Engineering)

Photo by RealToughCandy.com on Pexels
기존 변수들을 조합하거나 변형하여 모델에 더 유용한 새로운 변수를 만드는 과정입니다.
- 조합 (Combination): 두 개 이상의 변수를 더하거나 곱하거나 나누는 등 결합합니다. (예: BMI = 체중 / (키)^2)
- 변환 (Transformation):
- 로그 변환 (Log Transform): 비대칭 분포를 정규 분포에 가깝게 만들 때 사용합니다.
- 다항 변환 (Polynomial Features): 비선형 관계를 모델링하기 위해 변수의 거듭제곱 항을 추가합니다.
- 날짜/시간 변수 분해: 날짜에서 연, 월, 일, 요일, 시간 등을 추출합니다.
- 범주화 (Binning): 연속형 변수를 여러 구간으로 나누어 범주형 변수로 만듭니다. (예: 나이를 10대, 20대 등으로)
- 원-핫 인코딩 (One-Hot Encoding): 범주형 변수를 모델이 이해할 수 있는 이진 벡터 형태로 변환합니다.
# 변수 생성 예시: 날짜 변수 분해 및 BMI 계산
df_features = pd.DataFrame({
'timestamp': pd.to_datetime(['2023-01-15 10:30', '2023-02-20 14:00']),
'weight_kg': [70, 85],
'height_cm': [175, 180]
})
df_features['year'] = df_features['timestamp'].dt.year
df_features['month'] = df_features['timestamp'].dt.month
df_features['day_of_week'] = df_features['timestamp'].dt.dayofweek # 월요일: 0, 일요일: 6
# BMI 계산: height_cm을 m로 변환
df_features['height_m'] = df_features['height_cm'] / 100
df_features['BMI'] = df_features['weight_kg'] / (df_features['height_m'] ** 2)
print("\n변수 생성 후 DataFrame:\n", df_features)
2.5 전처리 및 변수 생성 워크플로우
데이터 전처리 및 변수 생성은 순서가 중요하며, 반복적인 과정일 수 있습니다.
graph TD
A["Raw Data (원시 데이터)"] --> B{"Data Exploration (데이터 탐색)"}
B --> C{Detect Missing Values (결측치 탐지)}
C -- Yes --> D["Impute/Delete Missing Values (결측치 처리)"]
C -- No --> E{Detect Outliers (이상치 탐지)}
D --> E
E -- Yes --> F["Handle Outliers (이상치 처리)"]
E -- No --> G{"Feature Engineering (변수 생성)"}
F --> G
G --> H{Categorical Encoding (범주형 변수 인코딩)}
H --> I{Scaling/Normalization (스케일링/정규화)}
I --> J["Ready for Modeling (모델링 준비 완료)"]
3. Worked Example
어떤 온라인 상점의 고객 구매 데이터가 있다고 가정해봅시다. 이 데이터에는 '구매금액', '고객나이', '결제수단', '구매일시' 변수가 포함되어 있으며 일부 결측치와 이상치가 있다고 가정합니다.
import pandas as pd
import numpy as np
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.compose import ColumnTransformer
from sklearn.impute import SimpleImputer
from sklearn.pipeline import Pipeline
# 1. 예시 데이터 생성
data = {
'PurchaseAmount': [10000, 25000, 5000, 150000, 30000, np.nan, 20000, 50000, 10000, 200000],
'CustomerAge': [25, 30, 60, 22, 35, 40, np.nan, 28, 70, 300], # 70세와 300세는 이상치 가정
'PaymentMethod': ['CreditCard', 'Cash', 'CreditCard', 'BankTransfer', 'CreditCard', 'Cash', 'CreditCard', 'BankTransfer', 'Other', 'CreditCard'],
'PurchaseDateTime': pd.to_datetime(['2023-01-05 10:00', '2023-01-10 14:30', '2023-01-20 18:00', '2023-02-01 09:15', '2023-02-15 11:00', '2023-03-01 16:45', '2023-03-10 12:00', '2023-03-25 10:00', '2023-04-01 15:00', '2023-04-10 17:30'])
}
df_customer = pd.DataFrame(data)
print("--- 원본 데이터 ---")
print(df_customer)
print("\n결측치:\n", df_customer.isnull().sum())
# 2. 변수 생성 (Feature Engineering)
# 'PurchaseDateTime'에서 'day_of_week'와 'hour' 추출
df_customer['PurchaseDayOfWeek'] = df_customer['PurchaseDateTime'].dt.dayofweek
df_customer['PurchaseHour'] = df_customer['PurchaseDateTime'].dt.hour
# 'CustomerAge'를 이용해 'AgeGroup' 생성 (예: 20대, 30대 등)
df_customer['AgeGroup'] = pd.cut(df_customer['CustomerAge'], bins=[0, 19, 29, 39, 49, 59, 150],
labels=['~19', '20s', '30s', '40s', '50s', '60+'], right=True)
# 3. 이상치 처리 (간단하게 상위/하위 1% 제거로 가정, 여기서는 CustomerAge 300세 제거)
# 실제로는 더 정교한 방법 사용
df_customer = df_customer[df_customer['CustomerAge'] < 100] # 300세를 이상치로 간주하여 제거
df_customer = df_customer.reset_index(drop=True)
print("\n--- 이상치 (나이 300세) 제거 후 ---")
print(df_customer)
# 4. 전처리 파이프라인 구축 (결측치 처리, 스케일링, 인코딩)
# 수치형 변수: 'PurchaseAmount', 'CustomerAge', 'PurchaseDayOfWeek', 'PurchaseHour'
# 범주형 변수: 'PaymentMethod', 'AgeGroup'
# 수치형 변수 처리 파이프라인: 결측치(평균) -> 스케일링(StandardScaler)
numeric_features = ['PurchaseAmount', 'CustomerAge', 'PurchaseDayOfWeek', 'PurchaseHour']
numeric_transformer = Pipeline(steps=[
('imputer', SimpleImputer(strategy='mean')), # 평균으로 결측치 대체
('scaler', StandardScaler()) # 표준 스케일링
])
# 범주형 변수 처리 파이프라인: 결측치(최빈값) -> 원-핫 인코딩
categorical_features = ['PaymentMethod', 'AgeGroup']
categorical_transformer = Pipeline(steps=[
('imputer', SimpleImputer(strategy='most_frequent')), # 최빈값으로 결측치 대체
('onehot', OneHotEncoder(handle_unknown='ignore')) # 원-핫 인코딩
])
# ColumnTransformer를 사용하여 각 변수 유형에 맞는 전처리 적용
preprocessor = ColumnTransformer(
transformers=[
('num', numeric_transformer, numeric_features),
('cat', categorical_transformer, categorical_features)
])
# 5. 전처리 적용
processed_data = preprocessor.fit_transform(df_customer)
# 결과 확인 (Dense matrix 형태로 반환되므로 DataFrame으로 변환)
# 원-핫 인코딩 후 컬럼 이름을 얻기 위해 get_feature_names_out 사용
ohe_feature_names = preprocessor.named_transformers_['cat']['onehot'].get_feature_names_out(categorical_features)
all_feature_names = numeric_features + list(ohe_feature_names)
df_processed = pd.DataFrame(processed_data, columns=all_feature_names)
print("\n--- 전처리 및 변수 생성 최종 데이터 (모델링 준비 완료) ---")
print(df_processed.head())
print("\n최종 데이터 shape:", df_processed.shape)
4. Key Takeaways
- 데이터 전처리 및 변수 생성은 모델링 성능에 가장 큰 영향을 미치는 핵심 단계입니다.
- 결측치 처리는 데이터 손실을 최소화하면서 데이터의 통계적 특성을 유지하는 것이 중요합니다.
- 이상치는 데이터 분포를 왜곡하고 모델 학습을 방해하므로, 적절한 방법으로 처리해야 합니다.
- 데이터 스케일링은 알고리즘의 특정 가정(예: 거리 기반)을 충족시키고 수렴 속도를 향상시킵니다.
- 변수 생성은 도메인 지식을 활용하여 모델에 새로운 통찰력을 제공하는 강력한 방법입니다.
피해야 할 흔한 실수:
- 데이터 탐색 없이 섣불리 결측치나 이상치를 처리하는 것.
- 학습 데이터로만 스케일러를 fit하지 않고 전체 데이터로 fit하여 데이터 누수(data leakage)를 일으키는 것.
- 범주형 변수를 숫자처럼 취급하여 통계적 연산을 수행하는 것.
- 변수 생성에만 집중하여 과적합(overfitting) 가능성을 높이는 것.
5. Now Try It
당신에게 housing.csv 파일이 주어졌다고 가정해 보세요. 이 파일에는 집값 예측을 위한 다양한 정보가 포함되어 있습니다. 다음을 수행해 보세요:
1. ocean_proximity 변수의 결측치를 최빈값으로 처리하고, 원-핫 인코딩을 수행하세요.
2. total_rooms, total_bedrooms, population, households 변수에 대해 total_rooms와 total_bedrooms에서 결측치를 평균으로 대체한 후, 모든 4개 변수에 Min-Max 스케일링을 적용하세요.
3. total_bedrooms를 total_rooms로 나누어 가구당 침실 수 비율(bedrooms_per_room)이라는 새로운 변수를 생성해 보세요.
4. 처리된 데이터프레임의 첫 5행을 출력하여 결과를 확인하세요.
이 연습은 약 15분 정도 걸릴 거예요. 성공적으로 완료했다면, 다양한 데이터 전처리 및 변수 생성 기법을 능숙하게 적용할 수 있는 기본기를 다진 것입니다!
Frequently asked about 데이터 전처리 및 변수 생성
Study this next
Get the full 데이터 사이언스 curriculum
Clone the complete plan to your dashboard for unlimited AI-generated notes, practice quizzes, and a personalised revision schedule.
Save this course free