이항 변수화

범주형 변수 e..g...( male / female )을 0 또는 1로 나타내는 경우,

시간 / 돈 관련 연속형 변수와 범주형 변수( 0 , 1, 2, 3, 4 로 나태내어진 변수) 를 구분할것.

이항변수화 할때 ( 성별 : 0 = > 10, 1 = > 01 )이런식으로 바이너리 스트링으로 표현. e..g... 10대(0) => 100000, 20대(1) => 010000

이런식으로 바이너리 스트링으로 만드는것을 이항 변수화 라고 한다.

대표적 함수로 OneHotEncoder() 가 있다.

In [0]:
import pandas as pd
import numpy as np
from sklearn.preprocessing import OneHotEncoder
In [0]:
#범주형 변수 생성
#  [ 성별( 0, 1 ), 연령대( 0, 1, 2 ), 성적( 0, 1, 2, 3, 4 ) ]

data = np.array( [ [ 0, 1, 1 ], # 여성 30대 비학점
                   [ 0, 2, 2 ], # 여성 40대 씨학점
                   [ 1, 0, 3 ], # 남성 20대 디학점      
                   [ 1, 1, 4 ], # 남성 20대 에프학점
                   [ 0, 0, 0 ]  # 여성 20대 에이학점 
                 ])
                  
                  

OneHotEncoder 사용

In [0]:
ohe = OneHotEncoder()

ohe.fit( data )  # data 변수에 저장된 데이터에 맞추어 이항변수화 fitting 
/usr/local/lib/python3.6/dist-packages/sklearn/preprocessing/_encoders.py:415: FutureWarning: The handling of integer data will change in version 0.22. Currently, the categories are determined based on the range [0, max(values)], while in the future they will be determined based on the unique values.
If you want the future behaviour and silence this warning, you can specify "categories='auto'".
In case you used a LabelEncoder before this OneHotEncoder to convert the categories to integers, then you can now use the OneHotEncoder directly.
  warnings.warn(msg, FutureWarning)
Out[0]:
OneHotEncoder(categorical_features=None, categories=None, drop=None,
              dtype=<class 'numpy.float64'>, handle_unknown='error',
              n_values=None, sparse=True)
In [0]:
#원핫 인코딩을 했을때 사용된 피쳐의 갯수를 리턴한다 성별 0 , 1 두개 성적 나이대 3개 성적 5개 즉 10개의 피쳐가 바이너리 스트링으로 표현된다.
# [ 남, 여, 20대, 30대, 40대, 에이학점, 비학점, 씨학점, 디학점, 에프학점 ]

ohe.active_features_
/usr/local/lib/python3.6/dist-packages/sklearn/utils/deprecation.py:100: DeprecationWarning: The ``active_features_`` attribute was deprecated in version 0.20 and will be removed 0.22.
  warnings.warn(msg, category=DeprecationWarning)
Out[0]:
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [0]:
## 종류의 갯수, 즉 성별은 두가지 종류 , 연령대 세가지 , 학점 다섯가지가 나온다, 각 피쳐별 범주의 갯수를 출력해준다.

ohe.n_values_
/usr/local/lib/python3.6/dist-packages/sklearn/utils/deprecation.py:100: DeprecationWarning: The ``n_values_`` attribute was deprecated in version 0.20 and will be removed 0.22.
  warnings.warn(msg, category=DeprecationWarning)
Out[0]:
array([2, 3, 5])
In [0]:
# 0이상 2 미만 => 성별을 표시하는 값의 범위
# 2, 5 =>  2이상 5 미만,
# 5, 10 => 5이상 10 미만
# 한 피쳐가 차지하는 인덱스 범위를 알려주는 속성이다.

ohe.feature_indices_
/usr/local/lib/python3.6/dist-packages/sklearn/utils/deprecation.py:100: DeprecationWarning: The ``feature_indices_`` attribute was deprecated in version 0.20 and will be removed 0.22.
  warnings.warn(msg, category=DeprecationWarning)
Out[0]:
array([ 0,  2,  5, 10])
In [0]:
# 예시 ) 여성, 20대, 30대, 디학점, => [ 0, 1, 3 ]
# 이항변수화 => 10, 010, 00010

test = np.array( [[0, 1, 3]] )


ohe.transform(test) #  기본 반환형 sparse matrix
Out[0]:
array([[1., 0., 0., 1., 0., 0., 0., 0., 1., 0.]])
In [0]:
ohe.transform(test).toarray()


# 아래와 같은 변수를 사용해서 위의 인코딩된 데이터를 구분해서 이해할 수 있다.
ohe.feature_indices_
ohe.active_features_
Out[0]:
array([[0, 1, 3]])

예를 들어 타이타닉 데이터에서 호칭, 티켓 등급 등을 원핫 인코딩 할 수 있다.

In [0]:
# 연속형 변수 -> 이산화
# np.digitize(), np.where() : 연속형 변수 -> 이산화( 2개 이상 ) 

from pandas import DataFrame

np.random.seed(75)
df = DataFrame( {
    'd1' : np.random.randn(10),
    'd2' : [ 'x', 'x', 'x', 'x', 'x', 'y', 'y', 'y', 'y', 'y'  ]
})

df
Out[0]:
d1d2
0-0.709502x
10.112694x
20.477022x
31.935981x
40.450415x
5-1.188847y
60.613631y
7-0.178142y
81.346521y
91.161150y

d1 컬럼에 있는값을 기준으로 5개의 구간으로 나누고 몇번째 범주에 속하는 값인지 추가 피처를 생성

In [0]:
# 몇번째 구간에 속하는지 표시할 컬럼. d1컬럼에 있는 최소값 ~ 최대값을 5개의 균등한 구간으로 나누겠다.
# 넘파이 min, max 함수 사용

## 대괄호 하나 = > 시리즈로 리턴.
#df['d1']


## 대괄호 둘 = > df로 리턴.
df[['d1']].min()

# 또는
df.d1.min()
df.d1.max()


bins = np.linspace(df.d1.min(), df.d1.max(), 5 )
In [0]:
# 특정 구간에대한 정보를 담고 있는 bins에 맞게 속한 구간을 리턴해준다. 1~5 구간 (최소 ~ 최대) 5는 최대값을 의미한다.
np.digitize(df['d1'], bins)  
Out[0]:
array([1, 2, 3, 5, 3, 1, 3, 2, 4, 4])
In [0]:
df['d1_bin'] = np.digitize(df['d1'], bins)  
In [0]:
#구간화의 장점, 그룹화해서 1번그룹인 애들만 모아서 평균을 구하는등의 연산이 가능해진다, 

df
Out[0]:
d1d2d1_bin
0-0.709502x1
10.112694x2
20.477022x3
31.935981x5
40.450415x3
5-1.188847y1
60.613631y3
7-0.178142y2
81.346521y4
91.161150y4
In [0]:
df.groupby( by = "d1_bin")
Out[0]:
<pandas.core.groupby.generic.DataFrameGroupBy object at 0x7fa2eaf73828>
In [0]:
# 각 구간별로 2개 2개 3개 2개 1개 가 있음을 알 수 있다.
df.groupby( by = "d1_bin")['d1'].size()
Out[0]:
d1_bin
1    2
2    2
3    3
4    2
5    1
Name: d1, dtype: int64
In [0]:
# 각 그룹별 d1컬럼의 평균.
df.groupby( by = "d1_bin")['d1'].mean()
Out[0]:
d1_bin
1   -0.949175
2   -0.032724
3    0.513689
4    1.253836
5    1.935981
Name: d1, dtype: float64
In [0]:
# d1_bin 을 기준으로 그룹화 한후 d2 컬럼을 참조. 
# 그룹화 이후로 d2 컬럼의 x 또는 y가 몇건씩 있는지 확인,

df.groupby( by = "d1_bin")['d2'].value_counts()
Out[0]:
d1_bin  d2
1       x     1
        y     1
2       x     1
        y     1
3       x     2
        y     1
4       y     2
5       x     1
Name: d2, dtype: int64
In [0]:
# 3번째 구간에 속하는 데이터만 추출하고 싶을때, 불린 참조 사용 

## 3번 구간에 속하는 데이터만 따로 df2에 담았다.

df2 = df[ df['d1_bin'] == 3 ]  
Out[0]:
d1d2d1_bin
20.477022x3
40.450415x3
60.613631y3
In [0]:
# where를 사용하는 조건 참조, digitaize가 아니라 조건으로만 으로도 구간화 할 수 있다.

# 조건, 참, 거짓
# where( 조건, 참, 거짓 )


# D1 컬럼에 대해서 평균을 구하고자 할때는 그냥 mean(), 평균을 기준으로 평균보다 크다, 작다의 정보를 가지고있는 새로운 컬럼을 만들고 싶을때,


df['hl'] = np.where( df['d1'] >= df['d1'].mean() , 'high', 'low')
In [0]:
df
Out[0]:
d1d2d1_binhl
0-0.709502x1low
10.112694x2low
20.477022x3high
31.935981x5high
40.450415x3high
5-1.188847y1low
60.613631y3high
7-0.178142y2low
81.346521y4high
91.161150y4high
In [0]:
# high low  갯수
df.groupby('hl')['d1'].size()
Out[0]:
hl
high    6
low     4
Name: d1, dtype: int64
In [0]:
df.groupby('hl')['d1'].mean()
Out[0]:
hl
high    0.997453
low    -0.490949
Name: d1, dtype: float64
In [0]:
df.groupby('hl')['d1'].std()
Out[0]:
hl
high    0.591084
low     0.576501
Name: d1, dtype: float64
In [0]:
## high low만이 아니라 미들 추가.

# 25% 지점에 해당하는 수를 리턴.(오름차순)
Q1 = np.percentile(df['d1'], 25) ## 실제 데이터 셋에는 존재하지 않는 값이다. 데이터 구간을 100분위로 나눠서 25%지점.
Q3 = np.percentile(df['d1'], 75)


# np.where를 사용해서 Q3보다 크거나 같다면 high, Q1보다 크거나 같다면 Medium , 나머지는 low

df['hml'] = np.where( df['d1'] >= Q3 , 'high',
         np.where(df['d1'] >= Q1 , 'Medium', 'low'))
In [0]:
df
Out[0]:
d1d2d1_binhlhml
0-0.709502x1lowlow
10.112694x2lowMedium
20.477022x3highMedium
31.935981x5highhigh
40.450415x3highMedium
5-1.188847y1lowlow
60.613631y3highMedium
7-0.178142y2lowlow
81.346521y4highhigh
91.161150y4highhigh

다항 차수를 이용한 비선형적인 관계에대한 패턴을 표현하고 할때 다항변수화 해야 할 경우가 있다. polynimial features

In [0]:
data = np.arange(6).reshape(3,2)
data
Out[0]:
array([[0, 1],
       [2, 3],
       [4, 5]])
In [0]:
# 데이터를 2차항 변수 만들기, 
# x1과 x2라는 변수가 있을떄, 1, x1, x2, x1^2, x1*x2 , x2^2를 만들어 내는 함수.
# [ 0, 1 ] = > 1, 0, 1, 0, 0, 1 와 같이 두개의 변수를 다항변수 화 한다.

# [ 2, 3 ] = > 1, 2, 3,  4,  6,  8
# [ 4, 5 ] = > 1, 4, 5, 16, 20, 25

data
Out[0]:
array([[0, 1],
       [2, 3],
       [4, 5]])
In [0]:
# 다항변수화 하기위한 poly객체가 있다 2차항 이상의 식으로 줄 수도 있다.
from sklearn.preprocessing import PolynomialFeatures

poly = PolynomialFeatures()
poly.fit_transform(data)
Out[0]:
array([[ 1.,  0.,  1.,  0.,  0.,  1.],
       [ 1.,  2.,  3.,  4.,  6.,  9.],
       [ 1.,  4.,  5., 16., 20., 25.]])


'딥러닝 모델 설계 > Machine Learning' 카테고리의 다른 글

Day 4. Grouping, sorting, visualizing  (0) 2019.07.06
Day 4. Data Reconstruction  (0) 2019.07.06
Day 03. Scaler  (0) 2019.07.03
Day 03. Replacement  (0) 2019.07.03
Day 02. Pandas Review - 2  (0) 2019.07.02

+ Recent posts