파이썬 전처리

kimm·2026년 4월 4일

데이터 전처리


결측치를 확인하고 처리

import pandas as pd

data = {
    'Name': ['Alice', 'Bob', 'Charlie'],
    'Age': [25, None, 30],
    'Score': [90, 85, None]
}

df = pd.DataFrame(data)

print(df)

print("결측치 여부 확인:")
print(df.isnull())

print("컬럼별 결측치 개수:")
print(df.isnull().sum())

df_cleaned = df.dropna()
print("결측치 삭제 후 데이터:")
print(df_cleaned)

# Age 열의 평균값으로 결측치 대체
mean_age = df['Age'].mean() # 평균값 계산
df['Age'] = df['Age'].fillna(mean_age)
print("Age 열 평균값으로 결측치 대체:")
print(df)

# 특정 값으로 결측치 대체
df['Score'] = df['Score'].fillna(0)
print("Score 열 0으로 대체:")
print(df)

Name Age Score
0 Alice 25.0 90.0
1 Bob NaN 85.0
2 Charlie 30.0 NaN

결측치 여부 확인:
Name Age Score
0 False False False
1 False True False
2 False False True

컬럼별 결측치 개수:
Name 0
Age 1
Score 1
dtype: int64

결측치 삭제 후 데이터:
Name Age Score
0 Alice 25.0 90.0

Age 열 평균값으로 결측치 대체:
Name Age Score
0 Alice 25.0 90.0
1 Bob 27.5 85.0
2 Charlie 30.0 NaN

Score 열 0으로 대체:
Name Age Score
0 Alice 25.0 90.0
1 Bob 27.5 85.0
2 Charlie 30.0 0.0


이상치를 확인하고 처리

import pandas as pd

data = {
    'Height': [150, 160, 170, 180, 350]
}

df = pd.DataFrame(data)

print(df)

print("\n데이터의 최대값: ", df['Height'].max())
print("데이터의 최소값: ", df['Height'].min())

# IQR(Interquartile Range) 방법
# IQR은 데이터의 중간 50% 범위를 기준으로 이상치를 탐지하는 방법
# Q1 => 1사분위, 하위 25%에 해당하는 값
# Q3 => 3사분위, 상위 25%에 해당하는 값
# IQR = Q3 - Q1 (중간 50% 범위)
# 이상치 기준 : 값이 Q1 - 1.5 * IQR보다 작거나, Q3 + 1.5 * IQR보다 큰 경우

# IQR을 이용한 이상치 확인
Q1 = df['Height'].quantile(0.25) # 1사분위 값
Q3 = df['Height'].quantile(0.75) # 3사분위 값
IQR = Q3 - Q1 # IQR 계산

# 이상치 기준 계산
lower_bound = Q1 - 1.5 * IQR # 하한
upper_bound = Q3 + 1.5 * IQR # 상한

# 이상치 확인
outliers = df[(df['Height'] < lower_bound) | (df['Height'] > upper_bound)]
print("\nIQR 기준으로 찾은 이상치:\n", outliers)

# Z-스코어를 활용한 이상치 확인
# 데이터가 평균에서 얼마나 떨어져 있는지를 표준편차 단위로 나타냄
# 일반적으로 |Z| > 3이면 이상치로 간주
from scipy.stats import zscore

# Z-스코어 계산
df['Z-Score'] = zscore(df['Height'])
print("\nZ-스코어:\n", df)

outliers = df[df['Z-Score'].abs() > 3]
print("\nZ-스코어 기준으로 찾은 이상치:\n", outliers)

# IQR 기준으로 이상치 제거
df_cleaned = df[(df['Height'] >= lower_bound) & (df['Height'] <= upper_bound)]
print("\n이상치 제거 후 데이터:\n", df_cleaned)

# 이상치를 중앙값으로 대체
median_value = df[(df['Height'] >= lower_bound) & (df['Height'] <= upper_bound)]['Height'].median()
df['Height'] = df['Height'].apply(lambda x: median_value if (x < lower_bound or x > upper_bound) else x)
print("\n이상치를 중앙값으로 대체한 데이터:\n", df)

Height
0 150
1 160
2 170
3 180
4 350

데이터의 최대값: 350
데이터의 최소값: 150

IQR 기준으로 찾은 이상치:
Height
4 350

Z-스코어:
Height Z-Score
0 150 -0.696373
1 160 -0.562455
2 170 -0.428537
3 180 -0.294619
4 350 1.981985

Z-스코어 기준으로 찾은 이상치:
Empty DataFrame
Columns: [Height, Z-Score]
Index: []

이상치 제거 후 데이터:
Height Z-Score
0 150 -0.696373
1 160 -0.562455
2 170 -0.428537
3 180 -0.294619

이상치를 중앙값으로 대체한 데이터:
Height Z-Score
0 150.0 -0.696373
1 160.0 -0.562455
2 170.0 -0.428537
3 180.0 -0.294619
4 165.0 1.981985

수치형 데이터 전처리

# 구간화 하기
import pandas as pd

# 데이터 생성
data = {
    'Age': [15, 22, 35, 50, 72]
}

df = pd.DataFrame(data)

# 나이를 구간화 (10대, 20대, 30대, ...)
bins = [10, 20, 30, 40, 100] # 구간 경계 설정
labels = ['10대', '20대', '30대', '40대 이상'] # 각 구간의 이름
df['Age_Group'] = pd.cut(df['Age'], bins=bins, labels=labels)

print("나이 구간화 pd.cut():\n", df)

# 나이를 자동으로 3개의 구간으로 나누기
# 데이터가 특정 구간에 치우쳐 있으면 qcut() 활용
df['Age_Quantile'] = pd.qcut(df['Age'], q=3, labels=['하위', '중위', '상위'])

print("\n나이 자동 구간 나누기 pd.qcut():\n", df)

나이 구간화 pd.cut():

Age Age_Group
0 15 10대
1 22 20대
2 35 30대
3 50 40대 이상
4 72 40대 이상

나이 자동 구간 나누기 pd.qcut():

Age Age_Group Age_Quantile
0 15 10대 하위
1 22 20대 하위
2 35 30대 중위
3 50 40대 이상 상위
4 72 40대 이상 상위

# 스케일링은 수치형 데이터를 일정한 범위로 조정하는 작업
# 머신러닝 모델은 데이터를 비교할 때 값의 크기에 영향을 받을 수 있기 때문에, 스케일링이 필수적

from sklearn.preprocessing import MinMaxScaler
import pandas as pd

data = {
    'Height': [150, 160, 170, 180, 190]
}

df = pd.DataFrame(data)

# MinMaxScaler 적용(데이터를 0 ~ 1 사이로 변환하는 정규화 작업)
scaler = MinMaxScaler()
df['Height_Normalized'] = scaler.fit_transform(df[['Height']])

print("MinMaxScaler 정규화:\n", df)

# StandardScaler 표준화
# 데이터를 평균 0, 표준편차 1로 변환하는 작업
# 데이터의 분포를 표준 정규분포처럼 만들어줌

from sklearn.preprocessing import StandardScaler

data2 = {
    'Weight': [50, 60, 70, 80, 90]
}

df2 = pd.DataFrame(data2)

scaler2 = StandardScaler()
df2['Weight_Standardized'] = scaler2.fit_transform(df2[['Weight']])

print("\nStandardScaler 표준화:\n", df2)

Height Height_Normalized
0 150 0.00
1 160 0.25
2 170 0.50
3 180 0.75
4 190 1.00

StandardScaler 표준화:
Weight Weight_Standardized
0 50 -1.414214
1 60 -0.707107
2 70 0.000000
3 80 0.707107
4 90 1.414214


**범주형 데이터 전처리**
import pandas as pd
from sklearn.preprocessing import LabelEncoder

data = {
    'City': ['서울', '부산', '대구', '서울', '부산']
}

df = pd.DataFrame(data)

# 레이블 인코딩
# 데이터에 순서가 있는 경우 적합
# ex) "초급" -> 0, "중급" -> 1, "고급" -> 2
encoder = LabelEncoder() # 범주형 데이터를 숫자로 변환하는 도구

# ex) "서울" -> 2, "부산" -> 1, "대구" -> 0
df['City_Encoded'] = encoder.fit_transform(df['City'])

print(df)

import pandas as pd

data = {
    'City': ['서울', '부산', '대구', '서울', '부산']
}

df = pd.DataFrame(data)

# 원핫 인코딩
# 데이터에 순서가 없는 경우 적합
# ex) "서울", "부산", "대구" 와 같은 도시 이름
df_encoded = pd.get_dummies(df, columns=['City'])

df_encoded

기존 데이터 삭제

import pandas as pd

data = {
    'Name': ['Alice', 'Bob', 'Charlie', 'David'],
    'Age': [25, 30, 35, 40],
    'Score': [90, 85, 75, 60]
}

df = pd.DataFrame(data)

print(df)

# 행 삭제
# 2번 인덱스 삭제
df_dropped = df.drop(index=2)

print("\n2번 인덱스 삭제:\n", df_dropped)

# 열 삭제
# Score 컬럼 삭제
df_dropped = df.drop(columns=['Score'])

print("\nScore 컬럼 삭제:\n", df_dropped)

Name Age Score
0 Alice 25 90
1 Bob 30 85
2 Charlie 35 75
3 David 40 60

2번 인덱스 삭제:
Name Age Score
0 Alice 25 90
1 Bob 30 85
3 David 40 60

Score 컬럼 삭제:
Name Age
0 Alice 25
1 Bob 30
2 Charlie 35
3 David 40


profile
벨린이

0개의 댓글