[Data Preprocessing] Feature Extraction

Oolayla·2023년 2월 21일
0

플레이데이터

목록 보기
12/15
post-thumbnail

🕵🏻‍♀️ Feature Extraction

  • feature engineering에서의 feature extraction
  • 기존 feature에 기반하여 새로운 feature 생성

📜 과정

◽ 데이터 로드

** 타이타닉 데이터셋 다운로드

import numpy as np
import pandas as pd

DATA_PATH = '../data/titanic/'
df = pd.read_csv(DATA_PATH + 'train.csv')
df.columns = [i.lower() for i in df.columns]

◽ 데이터 확인

df.info()
df.describe(include="all")
df.head()

◽ 데이터 분리

from sklearn.model_selection import train_test_split

SEED = 0
x_train, x_test = train_test_split(df, random_state=SEED, test_size=0.2)
x_train.reset_index(drop=True, inplace=True)
x_test.reset_index(drop=True, inplace=True)

print(x_train.shape, x_test.shape)
((712, 12), (179, 12))

◽ Data Cleaning

필요없는 데이터 제거

print(x_train['passengerid'].nunique(), x_train.shape[0])
# 712 712

x_train.drop('passengerid', axis=1, inplace=True)
x_test.drop('passengerid', axis=1, inplace=True)

결측치 제거

# 각 걸럼별 결측치 개수
print(x_train.isnull().sum().sort_values(ascending=False))

# cabin 결측치 해결 (사용 X)
x_train = x_train.drop('cabin', axis=1)
x_test = x_test.drop('cabin', axis=1)

# age 결측치 해결 (중앙값으로 치환)
x_train['age'] = x_train['age'].fillna(x_train['age'].median())
x_test['age'] = x_test['age'].fillna(x_train['age'].median())

# embarked 결측치 해결 (최빈값으로 치환)
embarked_mode = x_train['embarked'].mode().values[0]
x_train['embarked'] = x_train['embarked'].fillna(embarked_mode)
x_test['embarked'] = x_test['embarked'].fillna(embarked_mode)

◽ Feature Extraction

# 데이터 타입 확인 
x_train.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 712 entries, 0 to 711
Data columns (total 10 columns):
 #   Column    Non-Null Count  Dtype  
---  ------    --------------  -----  
 0   survived  712 non-null    int64  
 1   pclass    712 non-null    int64  
 2   name      712 non-null    object 
 3   sex       712 non-null    object 
 4   age       712 non-null    float64
 5   sibsp     712 non-null    int64  
 6   parch     712 non-null    int64  
 7   ticket    712 non-null    object 
 8   fare      712 non-null    float64
 9   embarked  712 non-null    object 
dtypes: float64(2), int64(4), object(4)
memory usage: 55.8+ KB

수치형 데이터 타입 변환

# 뒤에 소수점이 모두 0이면 범주형 데이터일 가능성도 있음
pd.set_option('display.float_format', lambda x: '%.3f' % x)

df_number = df.select_dtypes(include=np.number)
df_number.describe()
passengeridsurvivedpclassagesibspparchfare
count891.000891.000891.000714.000891.000891.000891.000
mean446.0000.3842.30929.6990.5230.38232.204
std257.3540.4870.83614.5261.1030.80649.693
min1.0000.0001.0000.4200.0000.0000.000
25%223.5000.0002.00020.1250.0000.0007.910
50%446.0000.0003.00028.0000.0000.00014.454
75%668.5001.0003.00038.0001.0000.00031.000
max891.0001.0003.00080.0008.0006.000512.329
# survived
# 정수가 차지하는 메모리 수를 최대한 줄이기 위한 작업
x_train['survived'] = x_train['survived'].astype('int32')
x_test['survived'] = x_test['survived'].astype('int32')

# age
# 정수가 차지하는 메모리 수를 최대한 줄이기 위한 작업
x_train['age'] = x_train['age'].astype('int32')
x_test['age'] = x_test['age'].astype('int32')

# fare
# 실수가 차지하는 메모리 수를 최대한 줄이기 위한 작업
x_train['fare'] = x_train['fare'].astype('float32')
x_test['fare'] = x_test['fare'].astype('float32')

# pclass
# 수치형에서 범주형으로 변경
x_train['pclass'] = x_train['pclass'].astype('category')
x_test['pclass'] = x_test['pclass'].astype('category')

# sibsp
# 수치형에서 범주형으로 변경
x_train['sibsp'] = x_train['sibsp'].astype('category')
x_test['sibsp'] = x_test['sibsp'].astype('category')

# parch
# 수치형에서 범주형으로 변경
x_train['parch'] = x_train['parch'].astype('category')
x_test['parch'] = x_test['parch'].astype('category')

범주형 데이터 타입 변환

df_object = x_train.select_dtypes(include='object')
df_object.describe()
namesexticketembarked
count712712712712
unique71225693
topBoulos, Mrs. Joseph (Sultana)maleCA.2343
freq14657519
# 값이 한정적이라면 데이터 타입을 category로 바꾸는 것이 좋음

# sex
x_train['sex'] = x_train['sex'].astype('category')
x_test['sex'] = x_test['sex'].astype('category')

# embarked
x_train['embarked'] = x_train['embarked'].astype('category')
x_test['embarked'] = x_test['embarked'].astype('category')

중간 점검 (데이터 형식)

x_train.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 712 entries, 0 to 711
Data columns (total 11 columns):
 #   Column       Non-Null Count  Dtype   
---  ------       --------------  -----   
 0   passengerid  712 non-null    int64   
 1   survived     712 non-null    int32   
 2   pclass       712 non-null    category
 3   name         712 non-null    object  
 4   sex          712 non-null    category
 5   age          712 non-null    int32   
 6   sibsp        712 non-null    category
 7   parch        712 non-null    category
 8   ticket       712 non-null    object  
 9   fare         712 non-null    float32 
 10  embarked     712 non-null    category
dtypes: category(5), float32(1), int32(2), int64(1), object(2)
memory usage: 29.7+ KB

문자열

df_object = x_train.select_dtypes(include=object)
df_object.describe()
nameticket
count712712
unique712569
topBoulos,Mrs.
freq17

** 공백 제거

# 문자열 앞뒤로 화이트스페이스가 있을 수 있으니 이를 제거하는 작업

# name
x_train['name'] = x_train['name'].map(lambda x: x.strip())
x_test['name'] = x_test['name'].map(lambda x: x.strip())

# ticket
x_train['ticket'] = x_train['ticket'].map(lambda x: x.strip())
x_test['ticket'] = x_test['ticket'].map(lambda x: x.strip())

** 문자열 포함 여부

dict_designation = {
    'Mr.': '남성',
    'Master.': '남성',
    'Sir.': '남성',
    'Miss.': '미혼 여성',
    'Mrs.': '기혼 여성',
    'Ms.': '미혼/기혼 여성',
    'Lady.': '숙녀',
    'Mlle.': '아가씨',
    # 직업
    'Dr.': '의사',
    'Rev.': '목사',
    'Major.': '계급',
    'Don.': '교수',
    'Col.': '군인',
    'Capt.': '군인',
    # 귀족
    'Mme.': '영부인',
    'Countess.': '백작부인',
    'Jonkheer.': '귀족'
}


def add_designation(name):
    designation = 'unknown'
    for key in dict_designation.keys():
        if key in name:
            designation = key
            break
    return designation
x_train['designation'] = x_train['name'].map(lambda x: add_designation(x))
x_test['designation'] = x_test['name'].map(lambda x: add_designation(x))

x_train[['name', 'designation']].head()
namedesignation
0Boulos,Mrs.
1Kvillner,Mr.
2Mallet,Mr.
3Betros,Mr.
4Windelov,Mr.

** 문자열 분리

x_train['last_name'] = x_train['name'].map(lambda x: x.split(',')[0])
x_test['last_name'] = x_test['name'].map(lambda x: x.split(',')[0])

x_train[['name', 'last_name']].head()
namelast_name
0Boulos, Mrs. Joseph (Sultana)Boulos
1Kvillner, Mr. Johan Henrik JohannessonKvillner
2Mallet, Mr. AlbertMallet
3Betros, Mr. TannousBetros
4Windelov, Mr. EinarWindelov

집계

** pivot_table

df_pivot = pd.pivot_table(
    data=x_train, 
    index='pclass', 
    values='fare', 
    aggfunc='mean'
).reset_index()

df_pivot.columns = ['pclass', 'fare_mean_by_pclass']
df_pivot
pclassfare_mean_by_pclass
0183.370
1220.776
2313.839

그룹

agg_dict = {'survived': 'mean', 'sibsp': 'nunique', 'parch': 'nunique'}
df_groupby = x_train.groupby('pclass').agg(agg_dict).reset_index()
df_groupby.columns = ['pclass', 'survived_by_pclass', 'len_sibsp_by_pclass', 'len_parch_by_pclass']
df_groupby
pclasssurvived_by_pclasslen_sibsp_by_pclasslen_parch_by_pclass
010.60736244
120.48344444
230.24120677

시계열 데이터

  • 날짜 형식의 컬럼이 존재할 때 사용

  • (▼ titanic 데이터 아님)

    ColumnNon-Null CountDtype
    date142524 non-nulldatetime64[ns]

df_cinemaTicket[['date']].head()
date
02018-05-05
12018-05-05
22018-05-05
32018-05-05
42018-05-05
print(df_cinemaTicket['date'].dt.year.head(3))
print(df_cinemaTicket['date'].dt.month.head(3))
print(df_cinemaTicket['date'].dt.day.head(3))
print(df_cinemaTicket['date'].dt.weekday.head(3)) # 0: 월, 6: 일
print(df_cinemaTicket['date'].dt.dayofyear.head(3)) # 연 기준 며칠째
print(df_cinemaTicket['date'].dt.quarter.head(3)) # 분기
0    2018
1    2018
2    2018
Name: date, dtype: int64

0    5
1    5
2    5
Name: date, dtype: int64

0    5
1    5
2    5
Name: date, dtype: int64

0    5
1    5
2    5
Name: date, dtype: int64

0    125
1    125
2    125
Name: date, dtype: int64

0    2
1    2
2    2
Name: date, dtype: int64
profile
울레일라

0개의 댓글