Kaggleコンペの流れ-Titanicの上位者から学ぶ- N/Aなど欠損値を対応する【Kaggle チャレンジ2日目】

はじめに

昨日公式の動画を見て学んでいたですが、ちょっとひと息
実際にブロンズを取った人のやっていることをトレースしてみようと思い立ったのでまとめてみようと思います。
今回トレースするのはこちら
コンペの内容はタイタニックの乗客のデータから、生存者の予測をしようというものです。
学習データのカラムは以下です。

スクリーンショット 2021-11-14 20.56.57

ざっくりですが、大きく3段階あるなと思いました。
①N/Aなど欠損値を対応する
②データセットから目的変数と相関の強い説明変数を探す
③機械学習

①N/Aなど欠損値を対応する

まずはデータを読み込んで欠損値を探します。

#モジュールたちを読み込む
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

#学習データとテストデータを分けて読み込む
train = pd.read_csv("train.csv")
test = pd.read_csv("test.csv")

train.head(10)

スクリーンショット 2021-11-14 20.55.26

見てみると、AgeとCabinに欠損値がありそうなことがわかります。

実際にnullを探す、info()を使うと

#missing values探し CabinAgenullがありそう
train.info()

スクリーンショット 2021-11-14 20.58.19

891が全データの行数であるので、Age、Cabin、Embarkedに欠損値があることがわかりました。
ちなみにCabinは客室番号、Embarkedはタイタニック号に乗った港を指すもののようです。
Cabinに欠損値が多い.....

問題のCabinカラムを推測や確からしい値を入れることができないか判断するために、中身をみてみます。
素人くさい感想ですが、value_counts()使っているのがおしゃれだなと思いました笑

#Cabinの中身を見てみます
train["Cabin"].value_counts()

スクリーンショット 2021-11-14 21.06.05

一番下の行にCabinカラムには、147種類の行があるようです。
これでは予測することも、確からしい値入れることも難しいという判断になったようです。よってCabinカラムは除外します。
PassengerIdも生存/死亡に関係がなさそうかつ、PassengerIdの左にカラムに通し番号が振られており、判別もできるので除外します。

#PassengerIdとCabinカラムを学習データから除外する
train.drop("PassengerId", axis=1, inplace=True)
train.drop("Cabin", axis=1, inplace=True)

次にAgeの欠損値の対応をします。
Ageでは分布がある程度予測できるものではあるので、中央値or平均値の値がより確からしいものを使うアプローチをしています。
まずは基本統計量を見るところから

#学習データの基本統計量を見る
train.describe()

スクリーンショット 2021-11-14 21.23.05

続いてAgeの分布を見てみます。

#Ageの分布を見る
x = train["Age"]
sns.distplot(x)

スクリーンショット 2021-11-14 21.24.24

中央値と平均値は基本統計量から出ているのですが、最頻値だけないので計算します。

#最頻値を学習データから計算する
print(train["Age"].mode()[0])

スクリーンショット 2021-11-14 21.27.21

分布より今回は平均値でも中央値でも最頻値でも問題がなさそうです。
この方は中央値を採用しています。
中央値が一番丸い回答な気がします。
平均値は一般に外れ値の影響を強く受けすぎるというデメリットがあるのですが、計算上都合が良いことも多いので、個人的には嫌いではないです。
最頻値はデータの数で判断するため、データ量が多い時は問題ないのですが、例えば[1, 1, 1, 15, 10000]などの時に最頻値は1になりますが、1に近い値がたくさん並んでいるかと言われるとそうでもないことがわかります。
したがって中央値を欠損値のところに埋めます。

#欠損値に中央値を入れる
median = train["Age"].median()
train["Age"].fillna(median,inplace = True)

最後の欠損値がEmbarked(タイタニック号に乗った港)です。
先ほどvalue_counts()でも良いはずですが、count_plotを使っています。
こちらの方が視覚的にわかりやすいですね。

#Embarkedの中身の分布を見てみる
sns.countplot(train["Embarked"])

スクリーンショット 2021-11-14 21.48.51

明らかにSが多いことがわかります。
欠損値に何が入っているのかわかりませんが、CやQを埋めるよりは確率が高そうなのでSを入れることにします。

#欠損値にSを入れる
train["Embarked"].fillna("S",inplace = True)

これで欠損値が埋まったはずです。
データセットから欠損値がなくなったかを確認します。

#データセットをもう一回みてみる
train.info()

スクリーンショット 2021-11-14 21.53.19

全てのカラムから欠損値が消えていることがわかります。
ここまでで「①N/Aなど欠損値を対応する」が終了します。

まとめ

流れをおさらいすると
(a)info()を使って、どのカラムに欠損値が存在するかを特定する。
(b)value_counts()やseabornのcountplotを使いどのような値がどのように分布しているのかを見ます。
(c)欠損値を埋める時は、数値なら値の分布を見ながら平均値と中央値、最頻値を使う。文字列でも分布を見ながら確からしいものを入れる。入れるときはfillna、無理ならdrop。

本当は全て1記事で書きたかったのですが、長くなってしまったので、また別の記事で書こうと思います。
内容は基本的なことかもしれませんが、かなり定石的な動きな気がしたので記事にしてみました。

最後まで読んでいただいた方ありがとうございました!

この記事が気に入ったらサポートをしてみませんか?