본문 바로가기
[AI+X 역량 강화] 인공지능/2) 주특기 심화: 머신러닝, 딥러닝

[머신러닝] #3 정형데이터 전처리 실습 // 결측치 처리(평균, 최빈값), 정규화, missingno

by 'here' 2023. 9. 16.

오늘은 '위스콘신 대학의 유방암 진단 분류 데이터'를 가지고 데이터 전처리를 진행해 볼 것이다.
원래 문제없는 데이터인데, 실습을 위해서 여기저기 결측치 값을 일부러 만들었다.
정형 데이터에 대해서 결측치 처리하는 방법과 범주형 데이터의 정규화 등 데이터를 전처리하는 과정에 대해서 알아보자.


전반적인 데이터 전처리 과정은 아래와 같다.

1. 데이터 불러오기
2. Explorating
3. 결측치 처리: strategy(remove, imputation)
4. Scaling
5. Data Split

 

0. 라이브러리 불러오기

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import sklearn
import seaborn as sns

 

1. 데이터 불러오기

wbsc = pd.read_csv('./wbcs_data_modified.csv')
wbsc
# 통계 알아보기(평균, 중앙값, 최빈값 등)
wbsc.describe()

# columns에 대한 정보 한눈에 보기
wbsc.info()

 

2. 결측치 처리

1) 결측치 데이터 알아보기

# 결측치 값이 있을 경우 True, 데이터가 있는 경우 False
wbsc.isnull()   

# 각 column의 결측치 개수
wbsc.isnull().sum()

이 데이터에서는 radius_mean(49개), concavity_se(18개), area_worst(18개)에 결측치가 있다고 나온다.
 
결측치값을 그래프로 보기 위해서는 missingno 라이브러리를 가져와야 한다.

!pip install missingno
import missingno as msno
  • Matrix: 결측치 분포 확인
msno.matrix(wbsc)
  • Bar: 결측치 개수 확인
msno.bar(wbsc)

2) 대체 또는 제거

우선, 원본 파일을 새로운 곳에 복사를 해준다.

df = wbsc   # shallow copy
df
  • 결측치 삭제
msno.matrix(df.dropna())
df_remove = df.dropna()   # 삭제한 데이터 복사
  • 결측치 대체: 평균 or 최빈값
from sklearn.impute import SimpleImputer

df2 = wbsc

imputer_mean = SimpleImputer(strategy="mean")   # 평균값으로 결측치를 대체하는 클래스 인스턴스
imputer_mf = SimpleImputer(strategy="most_frequent")   # 최빈값으로 결측치를 대체하는 클래스 인스턴스

둘 중 필요한 것을 선택해서 사용하면 된다. 어떤 걸 선택하는지에 따라 모델의 성능이 달라질 수 있다.

# 평균값 대체
df2 = wbsc

df2['radius_mean'] = imputer_mean.fit_transform(df2[['radius_mean']])
df2['concavity_se'] = imputer_mean.fit_transform(df2[['concavity_se']])
df2['area_worst'] = imputer_mean.fit_transform(df2[['area_worst']])

# 최빈값 대체
df3 = wbsc

df3['radius_mean'] = imputer_mf.fit_transform(df3[['radius_mean']])
df3['concavity_se'] = imputer_mf.fit_transform(df3[['concavity_se']])
df3['area_worst'] = imputer_mf.fit_transform(df3[['area_worst']])

3) 확인하기

# 데이터 개수 확인
df_remove.shape, df2.shape, df3.shape

# 데이터 통계 확인
df.describe(), df_remove.describe(), df2.describe(), df3.describe()

 

3. 범주형 데이터 Encoding

df['diagnosis'].unique()

encode_diag이라는 새로운 column을 만들어, M이라면 1, B라면 0의 숫자형 데이터로 변환해 준다. 

# one-hot encoding
def one_hot(row):
    if 'M' in row: return 1
    else: return 0
    
# apply()
df['encode_diag'] = df['diagnosis'].apply(one_hot)  # 새로운 column이 생김
df.tail(20)

아까 전처리했던 데이터에도 적용해주자.

df2['encode_diag'] = df2['diagnosis'].apply(one_hot)
df3['encode_diag'] = df3['diagnosis'].apply(one_hot)

df2[["diagnosis", "encode_diag"]]

 
※ 데이터 Scatter Plot

num_columns = 3
num_rows = (df.shape[1] + num_columns - 1) // num_columns
fig, axes = plt.subplots(num_rows, num_columns, figsize=(25, 100))

for i, column in enumerate(df.columns):
    ax = axes[i // num_columns, i % num_columns]
    ax.scatter(df.index, df[column], label=column)
    ax.set_xlabel('Index')
    ax.set_ylabel('Values')
    ax.set_title(f'Scatter Plot - {column}')
    ax.legend()

 

4. 데이터 정규화 (Data Normalization)

# MinMax Normalization
from sklearn.preprocessing import MinMaxScaler as MMS
# Dataset -> split; X: imput, y: label
# x: Label을 제외한 모든 column
# y: Label <- diagnosis => encode_diag
x = df.drop(['id', 'diagnosis', 'encode_diag'], axis=1) # axis = 1: column drop
y = df['encode_diag']
       
df.shape, x.shape, y.shape
scaler = MMS()

scaler.fit(x)
x_norm = scaler.transform(x)
x_norm = pd.DataFrame(x_norm, columns=x.columns)

# x_norm = pd.DataFrame(scaler.fit_transform(x), columns=x.columns)
x_norm

 

5. Data Split

# Train:Test = 7:3
from sklearn.model_selection import train_test_split as tts
x_train, x_test, y_train, y_test = tts(x_norm, y, test_size=0.3, random_state=812)
x_train.shape, x_test.shape, y_train.shape, y_test.shape

그리고 전저리된 데이터에도 적용을 시키자.

x2 = df_remove.drop(['id', 'diagnosis', 'encode_diag'], axis=1)
y2 = df_remove['encode_diag']

 
 
 
 

※ 해당 카테고리는 딥노이드, 오픈놀, 앙트비에서 주최하는 '<스타트업 유니버시티: DX Challenge 교육> AI+X 역량 강화 트랙'에 대한 기록입니다.