Handling Categorical Variable

Rainy Night for Sapientia·2023년 6월 11일
0

Handling Categorical Variable

범주형 변수(Categorical Variable)을 처리하는 주요 방법에 대해서 정리해보도록 하겠습니다.

참고로 Categorical variable을 핸들링하기 전에 가장 중요한 것 중하나는 먼저 Missing values를 어떻게 처리할 것(이미 처리했거나, 하나의 범주 지표로 놔두거나) 인지가 선행되어야 합니다. 특정 라이브러리들은 NaN값을 처리하지 못하기 때문입니다.

Categorical Variables의 종류

  1. Nominal variables : 순서가 없는 값 (cat, dog)
  2. Ordinal variables : 순서가 있는 값 (low, medium, high)
  3. Binary variables : 이진 값 (1, 0)
  4. Cyclic variables : 순환 값 (월, 화, 수, 목, 금, 토, 일)

Categorical Variable을 나누는 방법

나누는 방법에는 굉장히 여러가지가 있겠지만 dtypes를 이용하여 간단하게 나누는 코드 예는 다음과 같이 작성해볼 수 있습니다.

num_col = [col for col in df.columns if df[col].dtypes == 'int64' or df[col].dtypes == 'float64' ]
cat_col = [col for col in df.columns if df[col].dtypes == 'object' ]

1. Mapping

데이터의 순서(Order)가 존재하는 Ordinal variables를 대상으로 가장 손쉽게 핸들링할 수 있는 방법입니다.

다음과 같이 mapping정보가 담긴 딕셔너리를 생성해서 df.map() 메소드로 매핑해주면 끝입니다.

mapping = {
    "Freezing":0,
    "Warm": 1,
    "Cold": 2,
    "Boiling Hot": 3,
    "Hot": 4,
    "Lava Hot": 5
}

train["ord"] = train["ord"].map(mapping)

2. One-Hot encoder

데이터의 특정한 순서가 없는 범주형 데이터(Nominal) 같은 경우는 범주의 수로 columns를 확장하여 해당 범주 값이 존재하면 1, 존재하지 않으면 0으로 표현하는 One-Hot encoder가 가장 유명한 방법 중 하나입니다.

sklearn.preprocessing의 라이브러리를 사용하여 구현할 수 있는데, OH encoder의 경우의 특성상 희소행렬(sparse matrix)가 형성됩니다.
이는 데이터용량을 많이 잡아먹기 때문에 CSR(Compressed Sparsed Row)라는 형태로 저장하게 됩니다. 다음 코드를 보면 그냥 0과 1로 저장하는 dense행렬과, csr형태로 저장하는 경우의 용량의 차이가 존재함을 확인할 수 있습니다.

from sklearn import preprocessing
import scipy as sp

train = pd.read_csv(path+"train.csv")
df = train.copy()

oh_enc_dense = preprocessing.OneHotEncoder(sparse_output=False)
encoded_df_dense = oh_enc.fit_transform(df.ord_0.values.reshape(-1, 1))

oh_enc_csr = preprocessing.OneHotEncoder(sparse_output=True)
encoded_df_csr = oh_enc_csr.fit_transform(df.ord_0.values.reshape(-1, 1))

print(f'dense mat size = {encoded_df_dense.nbytes}')

print('sparse mat size =')
print('indptr:', encoded_df_csr.indptr.nbytes)
print('indices:', encoded_df_csr.indices.nbytes)
print('data:', encoded_df_csr.data.nbytes) 
print(f'= {encoded_df_csr.indptr.nbytes + encoded_df_csr.indices.nbytes + encoded_df_csr.data.nbytes}')

# print
dense mat size = 7200000
sparse mat size =
indptr: 1200004
indices: 1200000
data: 2400000
= 4800004

사이킷런을 이용하지 않고, 판다스로 수행할 수 있는 방법도 있습니다.
drop_first 인자를 활용하면 자명한 컬럼 하나를 줄일 수 있습니다.

pd.get_dummies(data, columns = ['Class'], drop_first=True)

3. Count Replacing

범주의 숫자를 하나의 새로운 피처로 활용하는 방법도 사용할 수 있다.

# Replacing to Count
df = train.copy()

# groupby to pk
df.groupby(["nom_0"])["id"].count() 

# aggregate
df.groupby(["nom_0"])["id"]\
.agg(["count"])\
.sort_values(by=["nom_0"], ascending=False)
profile
Artificial Intelligence study note

0개의 댓글