前回の記事ではタイタニックのデータセットの外れ値の処理をまとめていました。
今回は 3 特徴量エンジニアリング (Feature Engineering)の作業をしようと思います。
特徴量エンジニアリングに関してはKaggleの下記コードが参考になりました。
https://www.kaggle.com/code/gunesevitan/titanic-advanced-feature-engineering-tutorial
こちらの記事でどんな追加変数を作成しようか検討していました。
- 一緒に乗船している家族の人数を作成。さらに1人での乗船かどうかのフラグも作成
- 1人での乗船でもTicketは同じ番号だと知人と一緒に乗船しているようですので、Ticket番号の重複数をカウントした変数を作成
- Nameから敬称を抽出が可能なようです (Mr,Mrs,Dr.など)。特定の敬称は生存率が高いようです。
- ダミー変数の作成。カテゴリ型の変数を各区分ごとに1/0のフラグにした変数を作成。0/1に変換することによって、機械学習に投入することが可能になります。
1番と2番ですと、2番だけでもよいかもしれません。こちらはとりあえず作成だけしておいて、次の変数選択の作業のときに残すか残さないかを考えたいと思います。
3番は最終的に区分を作成するようです。Mr、Ms/Mrs/Miss、Dr/Militaryなどの区分を名前の名称から作成できるようです。
基本的には性別フラグで代用可能かな?と思うので今回の特徴量エンジニアリングでは作成するのはやめました。
それでは、特徴量エンジニアリングをしていきたいと思います。
タイタニックのデータセットの読み込み
import pandas as pd
import numpy as np
# タイタニックデータセットの訓練データを読み込み
df = pd.read_csv("/Users/hinomaruc/Desktop/notebooks/titanic/train.csv")
家族数の算出
タイタニックのデータセットではなぜか兄弟・配偶者と両親・子供の数が分かれているので、合計人数が分かるように渡航家族メンバーの数を算出します。
# the number of family member travelling with. including him/her self
df['FamilyCnt'] = df['SibSp'] + df['Parch'] + 1
1は自分自身の数を足しています。
# 計算結果の確認
df[["FamilyCnt","SibSp","Parch"]]
FamilyCnt SibSp Parch 0 2 1 0 1 2 1 0 2 1 0 0 3 2 1 0 4 1 0 0 ... ... ... ... 886 1 0 0 887 1 0 0 888 4 1 2 889 1 0 0 890 1 0 0 891 rows × 3 columns
チケット番号の重複人数を計算
同じチケット番号で乗船している人数を計算します。
家族だけではなく、友人やメイドなどの従者と乗船している人もいるので同行者という意味ではチケットの重複数がいい説明変数になってくれそうです。
# The number of members who may travel with using the same ticket number. probably correlated to FamilyCnt
df["SameTicketCnt"] = df.groupby('Ticket')["Ticket"].transform('count')
df.head()
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked FamilyCnt SameTicketCnt 0 1 0 3 Braund, Mr. Owen Harris male 22.0 1 0 A/5 21171 7.2500 NaN S 2 1 1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1 0 PC 17599 71.2833 C85 C 2 1 2 3 1 3 Heikkinen, Miss. Laina female 26.0 0 0 STON/O2. 3101282 7.9250 NaN S 1 1 3 4 1 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35.0 1 0 113803 53.1000 C123 S 2 2 4 5 0 3 Allen, Mr. William Henry male 35.0 0 0 373450 8.0500 NaN S 1 1
# husband and wife travelling together using the same ticket number
df.loc[df["Ticket"] == "113803"]
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked FamilyCnt SameTicketCnt 3 4 1 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35.0 1 0 113803 53.1 C123 S 2 2 137 138 0 1 Futrelle, Mr. Jacques Heath male 37.0 1 0 113803 53.1 C123 S 2 2
ダミー変数の作成
カテゴリ型の変数はそのままだと機械学習に投入できないので、0/1のフラグに変換させて使うことが多いです。
今回はPclass、Sex、Embarkedの3変数をダミー変数化して使おうと思います。
Embarkedの欠損値処理
まずは欠損が存在するので置換します。
# chk missing value for Embarked column
df[df["Embarked"].isnull()]
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked FamilyCnt SameTicketCnt Pclass_str 61 62 1 1 Icard, Miss. Amelie female 38.0 0 0 113572 80.0 B28 NaN 1 2 1 829 830 1 1 Stone, Mrs. George Nelson (Martha Evelyn) female 62.0 0 0 113572 80.0 B28 NaN 1 2 1
2レコードあります。
# fill missing value for Embarked column
from sklearn.impute import SimpleImputer
# missing_values = int, float, str, np.nan or None
imp = SimpleImputer(missing_values=np.nan, strategy="most_frequent")
imp.fit(np.array(df.loc[:,"Embarked"]).reshape(-1,1))
df["Embarked"] = imp.transform(np.array(df.loc[:,"Embarked"]).reshape(-1,1))
# chk missing value for Embarked column again
df[df["Embarked"].isnull()]
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked FamilyCnt SameTicketCnt Pclass_str
nullがなくなりました。
Pclassのデータ型をstrに変更
Pclassのデータ型がintなのでこのままだと利用するライブラリではダミー変数化できませんでした。
そのためstr型に変更しておきます。
自分で条件文を書いてダミー変数を作成する場合はstrに変換する必要はありません。
# change datatype of Pclass to str for creating dummpy variables
df['Pclass_str'] = df['Pclass'].apply(str)
ダミー変数の作成処理
from sklearn.preprocessing import OneHotEncoder
enc = OneHotEncoder(categories='auto',handle_unknown='ignore') #エラーは0になるオプション
enc.fit(df[['Pclass_str','Sex','Embarked']])
OneHotEncoder(handle_unknown='ignore')
# OneHotEncoderでダミー化した変数をDataFrameに追加
cols=enc.get_feature_names_out(['Pclass_str','Sex','Embarked'])
df = df.join(pd.DataFrame(enc.transform(df[['Pclass_str','Sex','Embarked']]).toarray(),columns=cols))
# もう利用しないカラムなので削除します。
df = df.drop(columns=["Pclass_str"])
中身の確認
df.head()
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare ... FamilyCnt SameTicketCnt Pclass_str_1 Pclass_str_2 Pclass_str_3 Sex_female Sex_male Embarked_C Embarked_Q Embarked_S 0 1 0 3 Braund, Mr. Owen Harris male 22.0 1 0 A/5 21171 7.2500 ... 2 1 0.0 0.0 1.0 0.0 1.0 0.0 0.0 1.0 1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1 0 PC 17599 71.2833 ... 2 1 1.0 0.0 0.0 1.0 0.0 1.0 0.0 0.0 2 3 1 3 Heikkinen, Miss. Laina female 26.0 0 0 STON/O2. 3101282 7.9250 ... 1 1 0.0 0.0 1.0 1.0 0.0 0.0 0.0 1.0 3 4 1 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35.0 1 0 113803 53.1000 ... 2 2 1.0 0.0 0.0 1.0 0.0 0.0 0.0 1.0 4 5 0 3 Allen, Mr. William Henry male 35.0 0 0 373450 8.0500 ... 1 1 0.0 0.0 1.0 0.0 1.0 0.0 0.0 1.0 5 rows × 22 columns
まとめ
今回は特徴量エンジニアリングの作業をしました。
feature engineeringを自動でやってくれるライブラリもあったような気がするのでいつか試してみたいです。
次回は変数選択(feature selection)の作業に入ろうと思います。