2 분 소요

범주형 데이터 인코딩 방법

1) 순서가 없는 특성: One-Hot Encoding 더미변수화

  • pd.get_dummies: 문자열 데이터만 변환, 나머지 열은 그대로
# 예제 데이터 프레임 만들기

import pandas as pd
df = pd.DataFrame([['green', 'M', 10.1, 'class1'],
                   ['red', 'L', 13.5, 'class2'],
                   ['blue', 'XL', 15.3, 'class1']])
df.columns = ['color', 'size', 'price', 'classlabel']
df
color size price classlabel
0 green M 10.1 class1
1 red L 13.5 class2
2 blue XL 15.3 class1
pd.get_dummies(df[['price', 'color', 'size']]) # 인자에 범위 지정
price color_blue color_green color_red size_L size_M size_XL
0 10.1 0 1 0 0 1 0
1 13.5 0 0 1 1 0 0
2 15.3 1 0 0 0 0 1
pd.get_dummies(df['classlabel'])
class1 class2
0 1 0
1 0 1
2 1 0
# columns 매개 변수 사용: 변환하려는 특성을 구체적으로 지정 가능
pd.get_dummies(df[['price', 'color', 'size']], columns = ['size'])
price color size_L size_M size_XL
0 10.1 green 0 1 0
1 13.5 red 1 0 0
2 15.3 blue 0 0 1
# `drop_first` 매개 변수 True (첫번째 열 삭제)
pd.get_dummies(df[['price', 'color', 'size']], drop_first=True) # color_blue가 삭제됨
price color_green color_red size_M size_XL
0 10.1 1 0 1 0
1 13.5 0 1 0 0
2 15.3 0 0 0 1
  • sklearn.processing의 OneHotEncoder 사용법
from sklearn.preprocessing import OneHotEncoder

X = df[['color', 'price', 'size']].values
color_ohe = OneHotEncoder()

# 배열의 다른 2개 열 수정하지 않기 위해 첫번째 열만 적용 X[:, 0]
color_ohe.fit_transform(X[:, 0].reshape(-1, 1)).toarray()
array([[0., 1., 0.],
       [0., 0., 1.],
       [1., 0., 0.]])
  • 여러 개의 특성이 있는 배열에서 특정 열만 반환 시 ColumnTransformer 사용
from sklearn.compose import ColumnTransformer

X = df[['color', 'size', 'price']].values
c_transf = ColumnTransformer([
    ('one_hot', OneHotEncoder(), [0]),
    ('nothing', 'passthrough', [1, 2])]) # 그대로 두기

c_transf.fit_transform(X)
array([[0.0, 1.0, 0.0, 'M', 10.1],
       [0.0, 0.0, 1.0, 'L', 13.5],
       [1.0, 0.0, 0.0, 'XL', 15.3]], dtype=object)

2) 순서가 있는 특성 Mapping

  • Mapping 함수 만들거나 enumerate 활용
# 데이터 특성 간 산술적 차이 알고 있을 때
# XL = L +1 = M + 2

size_mapping = {
                'XL': 3,
                'L': 2,
                'M': 1 }

df['size'] = df['size'].map(size_mapping)
df
color size price classlabel
0 green 1 10.1 class1
1 red 2 13.5 class2
2 blue 3 15.3 class1
# 다시 문자열로 돌리고 싶을 때 사용하는 함수

inv_size_mapping = {v: k for k, v in size_mapping.items()}
df['size'].map(inv_size_mapping)
0     M
1     L
2    XL
Name: size, dtype: object
# numpy & enuemerate 함수 활용

import numpy as np
class_mapping = {label: idx for idx, label in enumerate(np.unique(df['classlabel']))}
class_mapping
{'class1': 0, 'class2': 1}
# 위와 동일하게 사용

df['classlabel'] = df['classlabel'].map(class_mapping)
df
color size price classlabel
0 green 1 10.1 0
1 red 2 13.5 1
2 blue 3 15.3 0
inv_class_mapping = {v: k for k, v in class_mapping.items()}
df['classlabel'] = df['classlabel'].map(inv_class_mapping)
df
color size price classlabel
0 green 1 10.1 class1
1 red 2 13.5 class2
2 blue 3 15.3 class1
  • sklearn LableEncoder 활용
from sklearn.preprocessing import LabelEncoder

class_label = LabelEncoder()
y = class_label.fit_transform(df['classlabel'].values)
y
array([0, 1, 0])
df['classlabel'] = class_label.fit_transform(df['classlabel'].values)
df
color size price classlabel
0 green 1 10.1 0
1 red 2 13.5 1
2 blue 3 15.3 0
# inverse_transform() 사용하면 원복 가능

inv_y = class_label.inverse_transform(y)
df['classlabel'] = inv_y
df
color size price classlabel
0 green 1 10.1 class1
1 red 2 13.5 class2
2 blue 3 15.3 class1
# 임계값 (threshold) 사용 인코딩

df['x > M'] = df['size'].apply(lambda x: 1 if x in ['L', 'XL'] else 0)
df['x > L'] = df['size'].apply(lambda x: 1 if x == 'XL' else 0)
del df['size']
df
color price classlabel x > M x > L
0 green 10.1 class1 0 0
1 red 13.5 class2 1 1
2 blue 15.3 class1 0 1

댓글남기기