본문 바로가기
IT,SW,Data,Cloud,코딩/Python

2023년6월7일 파이썬공부 - 피쳐엔지니어링

by 착실하게 2023. 6. 7.
반응형
import pandas as pd 
import numpy as np 

X_train = pd.read_csv('data_atype/X_train.csv')
y_train = pd.read_csv('data_atype/y_train.csv')
X_test = pd.read_csv('data_atype/X_test.csv')

md = X_train['workclass'].mode()[0]
print(md)
X_train['workclass'] = X_train['workclass'].fillna(md)
print(X_train.isnull().sum())

print("=========")
#최빈값이 월등히많은 데이터가 아니므로 그냥 새로운 값으로 채우는 케이스 
X_train['occupation']=X_train['occupation'].fillna('X')

print(X_train.isnull().sum())

# 결측치 채워줄 때 train 데이터만 할게 아니라 test 데이터도 해줘야 한다 
# 같이 해주기! 

X_train['workclass'] = X_train['workclass'].fillna(
  X_train['workclass'].mode()[0]
)
X_train['native.country'] = X_train['native.country'].fillna(
  X_train['native.country'].mode()[0]
)
X_train['occupation'] = X_train['occupation'].fillna('X')

X_test['workclass'] = X_test['workclass'].fillna(
  X_test['workclass'].mode()[0]
)
X_test['native.country'] = X_test['native.country'].fillna(
  X_test['native.country'].mode()[0]
)
X_test['occupation'] = X_test['occupation'].fillna('X')


value = int(X_train['age'].mean()) #train의 평균값으로 train과 test를 채움
print(value)
X_train['age'] = X_train['age'].fillna(value)
X_test['age'] = X_test['age'].fillna(value)

value = int(X_train['hours.per.week'].median())
print(value)
X_train['hours.per.week'] = X_train['hours.per.week'].fillna(value)
X_test['hours.per.week'] = X_test['hours.per.week'].fillna(value)

print("=============")
print(X_train.describe())

print(X_train[X_train['age'] <0])
#이상치처리. 나이가 마이너스인 데이터 행 삭제함 
print(X_train.shape)
X_train = X_train[X_train['age'] >0]
print(X_train.shape)

# IQR 로 확인 

cols = ['age','fnlwgt','education.num','capital.gain','capital.loss','hours.per.week']
for col in cols: 
  Q1 = X_train[col].quantile(0.25)
  Q3 = X_train[col].quantile(0.75)
  IQR = Q3-Q1 
  min_iqr = Q1 - 1.5 * IQR 
  max_iqr = Q3 + 1.5 * IQR 
  cnt = sum( (X_train[col]<min_iqr) | ( max_iqr < X_train[col] ) )
  print(f'{col}의 이상치 갯수: {cnt} 입니다.')
  
# train 데이터셋: 소수의 행은 삭제 가능함.

# test 데이터셋: 이상치,결측치 처리 시 test 데이터 행은 절대 삭제 하면 안된다. 예측해야하는 데이터 이므로! 

# 그러면 결측치가 많으면 어떻게 할 것인지? 
# 컬럼은 삭제 가능함. 
#다만 train 데이터와 test 데이터의 컬럼수와 컬럼명이 일치해야함. y(target) 제외 

#수치형 데이터와 범주형 데이터의 분리 
# 방법1) 컬럼명으로 분리 
# 방법2) select_dtypes함수사용

#numeric - int, float
n_train = X_train.select_dtypes(exclude='object').copy()
n_test = X_test.select_dtypes(exclude='object').copy()

#categorical #object
c_train = X_train.select_dtypes(include='object').copy()
c_test = X_test.select_dtypes(include='object').copy()

# Scaling
# 트리 기반의 모델은 입력의 스케일을 크게 신경쓰지 않아도 됨
# 선형회귀나 로지스틱 회귀 등과 같은 모델은 입력의 스케일링에 영향을 받음 

#스케일링 작업할 컬럼명 
cols = ['age','fnlwgt','education.num','capital.gain','capital.loss','hours.per.week']

#민-맥스 스케일링 MinMaxScaler (모든 값이 0과 1 사이)
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
print(n_train.head(2))
n_train[cols] = scaler.fit_transform(n_train[cols])
n_test[cols] = scaler.transform(n_test[cols])
#train으로 fit하고 transform, test로 변환만
print(n_train.head(2))

print("======================")
#numeric - int, float
n_train = X_train.select_dtypes(exclude='object').copy()
n_test = X_test.select_dtypes(exclude='object').copy()

#categorical #object
c_train = X_train.select_dtypes(include='object').copy()
c_test = X_test.select_dtypes(include='object').copy()


#표준화 
from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()
print(n_train.head(3))
n_train[cols] = scaler.fit_transform(n_train[cols])
n_test[cols] = scaler.transform(n_test[cols])
print(n_train.head(3))

# MinMaxScaler, StandardScaler 두가지는 이상치가 있을때 예쁘게 안된다는 단점이 있다. 
# 그럴 때 사용하는 것이 Robust Scaler 이다. 
print("======================")

#numeric - int, float
n_train = X_train.select_dtypes(exclude='object').copy()
n_test = X_test.select_dtypes(exclude='object').copy()

#categorical #object
c_train = X_train.select_dtypes(include='object').copy()
c_test = X_test.select_dtypes(include='object').copy()

# RobustScaler 
#로버스트 스케일링은 중앙값과 사분위값을 활용하기 때문에, 이상치의 영향이 최소화 된다는 장점이 있다. 
#로버스트 스케일링은 평균과 표준편차를 사용하지 않는다. 

from sklearn.preprocessing import RobustScaler

scaler = RobustScaler()
print(n_train.head())
n_train[cols] = scaler.fit_transform(n_train[cols])
n_test[cols]=scaler.transform(n_test[cols])
print(n_train.head())

#로그 변환
# X_train['fnlwgt'].hist()
# 데이터가 왼쪽에 극도로 치우쳐져 있는 케이스
print(X_train['fnlwgt'][:3])
print(np.log1p(X_train['fnlwgt'][:3]))
#정규분포에 가까운모양새로 바뀐다. 

#로그변환시킨걸 원래값으로 돌리려면?
#np.exp를 사용하면 된다. 하지만 완벽하게 돌아오지는 않는다. 
print(np.exp(np.log1p(X_train['fnlwgt'])))


#인코딩!
#라벨인코딩
#원핫인코딩

print(c_train.head())

#object컬럼명
# cols=['workclass','education','marital.status','occupation','relationship','race','sex','native.country']

# columns 주의 's' 붙어있음. 
#.columns붙여서 조건넣어야 dtypes 먹힘
#dtypes에 object조건 넣을땐 ''안써도 먹힘, 써도 먹힘 

cols = list(X_train.columns[X_train.dtypes==object])
print(cols)

# cols = list(X_train.columns[X_train.dtypes=='object'])
# print(li)


#라벨인코딩
from sklearn.preprocessing import LabelEncoder 
encoder = LabelEncoder()

print(c_train.head()) #인코딩 전 

for col in cols:  
  c_train[col] = encoder.fit_transform(c_train[col])
  c_test[col] = encoder.transform(c_test[col])

print(c_train.head()) #인코딩 후

#numeric - int, float
n_train = X_train.select_dtypes(exclude='object').copy()
n_test = X_test.select_dtypes(exclude='object').copy()

#categorical #object
c_train = X_train.select_dtypes(include='object').copy()
c_test = X_test.select_dtypes(include='object').copy()

print("===========================================")
#원핫 인코딩 # get_dummies 
# sklearn 에서 가져올 필요 없음. 판다스에서 제공해주고 있음.

print(c_train.head())
#원핫인코딩 해줄 대상 컬럼들: cols

c_train = pd.get_dummies(c_train[cols])
c_test = pd.get_dummies(c_test[cols])

print(c_train.head())
#country데이터 종류가 많다보니.. 컬럼이 백개이상 생겼음.

print("===========================================")




#데이터 합치기#
#수치형과 범주형으로 나누었던 데이터를 다시 합쳐주자.

X_train=pd.concat([n_train,c_train],axis=1)
X_test=pd.concat([n_test,c_test],axis=1)
print(X_train.shape,X_test.shape)
print(X_train.head())

#test,train 데이터셋의 컬럼 개수가 일치해야하는데 원핫인코딩 해버리면 컬럼개수가 이렇게 달라져버릴수있음

#이걸맞춰주려면?
#train,test를 먼저 합친 후, 원핫인코딩 실행후, 그 후에 다시 분리! 

#사과,배 만으로 fit 시켰는데 test에 딸기가 있으면 에러난다. 
#합쳐서 라벨인코딩 후, 다시 나눠서 fit_transform, transform 해야함

피쳐엔지니어링 (from sklearn.preprocessing import OOOOOO ) 

- 수치형: Scaler (MinMaxScaler, StandardScaler, RobustScaler)

- 범주형: Encoder (LabelEncoder, pd.get_dummies) 

 

import pandas as pd 
import numpy as np 

#데이터 합치기#
#수치형과 범주형으로 나누었던 데이터를 다시 합쳐주자.

# X_train=pd.concat([n_train,c_train],axis=1)
# X_test=pd.concat([n_test,c_test],axis=1)
# print(X_train.shape,X_test.shape)
# print(X_train.head())

#test,train 데이터셋의 컬럼 개수가 일치해야하는데 원핫인코딩 해버리면 컬럼개수가 이렇게 달라져버릴수있음

#이걸맞춰주려면?
#train,test를 먼저 합친 후, 원핫인코딩 실행후, 그 후에 다시 분리! 

#사과,배 만으로 fit 시켰는데 test에 딸기가 있으면 에러난다. 
#합쳐서 라벨인코딩 후, 다시 나눠서 fit_transform, transform 해야함

X_train = pd.read_csv('data_atype/X_train.csv')
X_test = pd.read_csv('data_atype/X_test.csv')
y_train = pd.read_csv('data_atype/y_train.csv')

print("shape: ",X_train.shape, X_test.shape)

# 참고 
# print(type(y_train # 결과 타입은 pandas.core.frame.DataFrame임

#cols: 원핫인코딩 대상 컬럼 
cols = list(X_train.columns[X_train.dtypes==object])

#train,test 합쳐서 원핫인코딩해보자
# 위아래로 합치는게 기본 설정임 axis = 0 
all_df = pd.concat( [X_train,X_test] ) #위아래로 합친상태임 
all_df = pd.get_dummies( all_df[cols] ) #cols에 대해 원핫인코딩 수행함 

#원핫인코딩 수행 후, 데이터를 라인으로 나누는 방법.
line = int( X_train.shape[0])
print(line)

X_train = all_df.iloc[:line,:].copy()
X_test = all_df.iloc[line:,:].copy()

print("shape: ",X_train.shape, X_test.shape)

#################################################
# (1) 데이터를 n 과 c 로 나눈다
# (2) 각각의 형태에 대해 전처리 수행 
# numerical - MinMaxScaler
# categorical - LabelEncoder
# (3) 분리했던 데이터 다시 합침
# (4) 출력
#################################################
반응형

댓글