#!/usr/bin/env python3


One-Hot-Encoding(가변수)


0.살펴보기

factor범주 변수를 표현하는데 가장 널리 쓰이는 방법인 One-Hot-Encoding원-핫-인코딩

dummy variable가변수을 만들어 factor형 변수를 0 또는 1 의 값을 가진 하나 이상의 새로운 특성으로 바꿈

따라서 특성당 0, 1의 값이 들어있기 때문에 binary classifier algorithm이진분류알고리즘 적용가능


pandas의 get_dummies[각주:1] 함수는 숫자 특성은 모두 연속형이라 생각해서 가변수를 만들지 않음 

대신 어떤 열이 연속형인지 범주형인지를 저장할 수 있는 scikit-learn의 OneHotEncoder를 사용할수 있고

DataFrame에 있는 숫자로 된 열을 문자열로 바꿀 수도 있음


# library import

import pandas as pd


# DataFrame 생성

df = pd.DataFrame({'숫자 특성': [0, 1, 2, 1],

                        'factor형 특성': ['핸드폰', '밀스', '핸드폰', '상자']})


# DataFrame 출력

print('df \n{}'.format(df))


# one-hot-encoding 적용

df_dummy = pd.get_dummies(df)

print('df_dummy \n{}'.format(df_dummy))


### get_dummies를 사용하면 문자열 특성만 인코딩되며 숫자 특성은 바뀌지 않음


### series를 str형태로 변형후 get_dummies 적용

### get_dummies를 적용할 때 columns를 직접 입력

### 방법 1

df1 = df.copy() #  DataFrame 복사

df1['숫자 특성'] = df1['숫자 특성'].astype(str) # 타입변형

df1_dummies = pd.get_dummies(df1)

print('df1_dummies \n{}'.format(df1_dummies))


### 방법 2

df2_dummies = pd.get_dummies(df, columns=['숫자 특성', 'factor형 특성']) # get_dummies 적용시 columns 지정

print('df2_dummies \n{}'.format(df2_dummies))



1. adult data loading

# library import

import pandas as pd


# data load

adult.csv

adult = pd.read_csv('adult.csv', index_col=False


# 원하는 열만 추출

adult = adult[['age', 'workclass', 'education', 'gender', 'hours-per-week', 'occupation', 'income']]

print('adult.head() \n{}'.format(adult.head()))

adult데이터의 처음 5번째 행


2. 범주형 데이터 문자열 확인

pandas ==> value_counts 메소드로 유일한 값이 각각 몇 번 나타나는지 확인


print('columns names \n{}'.format(adult.columns)) # 열 출력


print('age의 갯수 \n{}'.format(adult.age.value_counts())) # dataframe.열.메소드

print('workclass의 갯수 \n{}'.format(adult.workclass.value_counts())) # ? 값 있음을 확인

print('education의 갯수 \n{}'.format(adult.education.value_counts())) 

print('gender의 갯수 \n{}'.format(adult.gender.value_counts()))

print('hours-per-week의 갯수 \n{}'.format(adult['hours-per-week'].value_counts())) # 열이름이 특수문자나 띄어쓰기 있으면 ['열이름']으로 접근

print('occupation의 갯수 \n{}'.format(adult.occupation.value_counts())) # ? 값 있음을 확인

print('income의 갯수 \n{}'.format(adult.income.value_counts()))


value_counts로 확인한 특성의 수



3. pandas의 get_dummies로 데이터 reshaping 


adult_dummies = pd.get_dummies(adult)

print('원본 특성:\n', list(adult.columns), '\n')

print('get_dummies 후의 특성 :\n', list(adult_dummies.columns))

원본 특성과 get_dummies후의 특성, 'age', 'hours-per-week'를 제외하고 전부 나뉘어진 것을 볼 수 있음


### 숫자형인 age, hours-per-week는 그대로지만 factor형 특성은 값마다 새로운 특성이 만들어짐

### pandas의 values속성을 이용해 numpy 배열로 바꿀수 있음

### target을 income으로 잡을 것이므로 income을 데이터에서 분리해야함


### numpy에서 np.arange(11)[0:10]은 인덱스가 10인 항목을 포함하지 않음

### 그러나 pandas에서 범위 끝은 그 열을 포함함

features = adult_dummies.loc[:, 'age':'occupation_ Transport-moving']


import numpy as np

x = features.values # feature를 numpy배열로 변환

y = adult_dummies['income_ >50K'].values # 타겟데이터를 numpy 배열로 변환


print('x.shape: {}. y.shape: {}'.format(x.shape, y.shape)) # x.shape: (31143, 44), y.shape:(31143,)



4. one-hot-coding한 데이터를 바탕으로 machine learning

from sklearn.linear_model import LogisticRegression

from sklearn.model_selection import train_test_split


x_train, x_test, y_train, y_test = \

  train_test_split(x, y,

                   test_size=0.3, random_state=0)


logreg = LogisticRegression().fit(x_train, y_train)

print('테스트 점수 \n{:.3f}'.format(logreg.score(x_test, y_test))) # 0.813


### adult 데이터셋에서는 factor형 변수가 문자열로 인코딩 되어있음

### 철자 오류가 날 수 있지만 다른 한 편으로는 변수가 factor형이란 것을 확실하게 알 수가 있음


### 하지만 저장 공간을 절약하거나 데이터 취합 방식에 따라 범주형 변수가 숫자로 인코딩 된 경우가 많음

### 예를들어 adult 데이터셋에 있는 인구조사 데이터가 설문지를 이용해 모은 것이라고 가정하면 workclass에 대합 대답은 0, 1 ,2 등이 됨 ==> 이 열은 0~8까지의 숫자로 채워지

### 게 되고 누군가 이 데이터셋을 보면 이 변수를 연속형으로 다뤄야할지 factor형으로 다뤄야할지 단번에 알아채기가 어려움. 그러나 숫자가 workclass를 나타낸다고 알게  되면

### 이  값은 이산적이므로 연속형 변수로 다루면 안된다는 것이 명확해짐



  1. 객체 타입(문자열 같은)이나 범주형을 가진 열을 자동으로 변환해줌 [본문으로]

+ Recent posts