범주형 데이터의 전처리
범주형 데이터를 수학으로 분석 가능하게 만드는 방법
데이터에 대한 수학적 분석을 통해 모델을 만드려면 반드시 모든 데이터가 숫자로 이루어져 있어야 한다.
pandas를 직접 전처리하거나 NumPy가 제공하는 함수를 사용해서 범주형 자료를 수치화하는 전처리 작업을 직접 진행할 수도 있지만, scikit-learn이나 pandas에서 인코딩을 쉽게 할 수 있는 API를 제공하고 있어 정리해둔다.
Label 인코딩¶
인코딩 대상 데이터를 0부터 n - 1까지의 숫자로 단순 인코딩하는 방법으로, 어떤 데이터가 어떤 숫자로 인코딩 될지 정할 수 없기 때문에 종속변수를 인코딩 할 때만 사용해야 한다.
from sklearn.preprocessing import LabelEncoder
enc = LabelEncoder()
enc.fit(["paris", "paris", "tokyo", "amsterdam"])
print(enc.transform(["tokyo", "tokyo", "paris"]))
Ordinal 인코딩¶
순서형 데이터를 인코딩 할 때는 scikit-learn의 OrdinalEncoder
를 활용하면 쉽게 처리할 수 있다.
위의 LabelEncoder
와 작동 원리는 동일하나 어떤 데이터를 어떤 숫자로 인코딩 할지 개발자가 커스텀할 수 있고, 커스텀을 위해 입력된 범주들에 없는 데이터가 있거나(unknown_value), 결측치가 있을 때 어떻게 처리할지(encoded_missing_value) 등을 지정할 수 있어 독립변수의 인코딩에 사용할 수 있다.
파라미터를 지정하여 사용하는 방법은 아래와 같다.
import numpy as np
from sklearn.preprocessing import OrdinalEncoder
enc = OrdinalEncoder(
categories=[['first', 'second', 'third', np.nan]], # custom categories order
handle_unknown='use_encoded_value', # in case unknown categorical feature input when transform
unknown_value=99, # value for unknown data when handle_unknown parameter is 'use_encoded_value'
encoded_missing_value=-1 # value for missing data
)
enc.fit([['third'], ['second'], ['first'], ['forth']])
print(enc.transform([[np.nan], ['fifth'], ['forth'], ['third'], ['second'], ['first']]))
OneHot 인코딩¶
순서형이 아닌 단순 명목형의 범주형 데이터를 인코딩 할 때는 OneHot 인코딩을 사용해야 한다.
scikie-learn¶
일정 카테고리를 drop 하면서 인코딩 되도록 설정할 수도 있고, sparse_output
파라미터를 통해 결과값이 SciPy의 csr_matrix
로 반환될지, 아니면 NumPy 배열로 반환될지 설정할 수 있다.
Info
구버전의 sparse
파라미터가 sparse_output
파라미터로 변경되었다.
import pandas as pd
from sklearn.preprocessing import OneHotEncoder
data = [['setosa'], ['versicolor'], ['virginica']]
enc = OneHotEncoder()
enc.fit(data)
encoded = enc.transform([['setosa'], ['versicolor'], ['virginica'], ['setosa'], ['setosa'], ['virginica']])
print(pd.DataFrame.sparse.from_spmatrix(data=encoded, columns=[v for x in data for v in x]))
import pandas as pd
from sklearn.preprocessing import OneHotEncoder
data = [['setosa'], ['versicolor'], ['virginica']]
enc = OneHotEncoder(sparse_output=False)
enc.fit(data)
encoded = enc.transform([['setosa'], ['versicolor'], ['virginica'], ['setosa'], ['setosa'], ['virginica']])
print(pd.DataFrame(data=encoded, columns=[v for x in data for v in x]))
setosa versicolor virginica
0 1.0 0.0 0.0
1 0.0 1.0 0.0
2 0.0 0.0 1.0
3 1.0 0.0 0.0
4 1.0 0.0 0.0
5 0.0 0.0 1.0
pandas¶
pandas에도 get_dummies
라는 API가 있는데, train 데이터의 특성을 저장하지 않기 때문에 train 데이터에만 있고 test 데이터에는 없는 카테고리를 test 데이터에서 처리할 수 없다는 점을 고려하여 전처리를 진행해야 한다.
import pandas as pd
data = {
'Species': ['setosa', 'versicolor', 'virginica'],
'tmp': ['a', 'b', 'c']
}
df = pd.DataFrame(data)
df = pd.get_dummies(
data=df,
columns=['Species'],
prefix='dummy'
)
print(df)