KaggleのTitanicでデータ分析を学ぶ

KaggleのTitanicでデータ分析を学びます。

私は最近Kaggleを始めた初心者です。
研究でPythonやRを使っておりデータ分析のスキルに少し自信があったのですが、Kaggleを始めてから、私のデータ分析スキルが微々たるものであることを痛感しました。
そこで、KaggleのTitanicでデータ分析を学び、データ分析スキルを上げようと思います。
この記事では、[Titanicコンペ](https://www.kaggle.com/competitions/titanic)のコードを書き、学んだことを書いていきます。

# ライブラリの読み込み
```Python
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
```

# データの読み込み
[pandas.dataframe](https://pandas.pydata.org/docs/reference/api/pandas.read_csv.html)を用いて、学習データ、テストデータ、提出データをデータフレームとして代入します。
```Python
train = pd.read_csv("/kaggle/input/titanic/train.csv")
test = pd.read_csv("/kaggle/input/titanic/test.csv")
gender_submission = pd.read_csv("/kaggle/input/titanic/gender_submission.csv")
```

# データの可視化
### Survivedの可視化
[seaborn.countplot](https://seaborn.pydata.org/generated/seaborn.countplot.html)を用います。
```Python
sns.countplot(x="Survived", data=train)
plt.show()
```

![スクリーンショット 2023-12-08 2.24.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569835/825f9780-c443-fc19-abf7-28c76524c362.png)


Survivedは、0がNo、1がYesです。
0のほうが多いことがわかります。
つまり、生存率は50%より低いことがわかります。

### Survived、Pclass、Age、SibSp、Parch、Fareの関係の可視化
[seaborn.pairplot](https://seaborn.pydata.org/generated/seaborn.pairplot.html)を用います。
```Python
sns.pairplot(train[["Survived", "Pclass", "Age", "SibSp", "Parch", "Fare"]])
plt.show()
```

![スクリーンショット 2023-12-08 0.37.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569835/b157069d-4ea5-a86e-589d-0ec435976194.png)

この図からは情報を読み取れないため、パラメータのhueをSurvivedに指定します。
```Python
sns.pairplot(train[["Survived", "Pclass", "Age", "SibSp", "Parch", "Fare"]], hue="Survived")
plt.show()
```

![スクリーンショット 2023-12-08 0.38.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569835/ac9ad1b7-c51e-56ea-7f80-5cd63209e7f0.png)

この図から、Pclassが3だと生存率が低く、Ageが低いと生存率が高いことがわかります。

### SurvivedとSexの可視化
[seaborn.catplot](https://seaborn.pydata.org/generated/seaborn.catplot.html)を用います。

```Python
g = sns.catplot(x="Sex",y="Survived", data=train, kind="bar")
g = g.set_ylabels("survival rate")
plt.show()
```

![スクリーンショット 2023-12-08 2.20.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569835/fb4e450f-ffda-b818-feec-09a262e8c3c5.png)


femaleのほうが生存率が高いことがわかります。

次に、[seaborn.countplot](https://seaborn.pydata.org/generated/seaborn.countplot.html)を用います。
```Python
sns.countplot(x="Sex", hue="Survived", data=train)
plt.show()
```

![スクリーンショット 2023-12-08 2.29.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569835/4b228986-3991-07f5-d2a2-22221716bea9.png)


maleの0が多いことがわかります。

### SurvivedとPclassの可視化
[seaborn.catplot](https://seaborn.pydata.org/generated/seaborn.catplot.html)を用います。
```Python
g = sns.catplot(x="Pclass",y="Survived", data=train, kind="bar")
g = g.set_ylabels("survival rate")
plt.show()
```

![スクリーンショット 2023-12-08 2.20.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569835/acf1a77a-1cc3-736d-b637-4290c0548139.png)

Pclassが小さいほど生存率が高いことがわかります。

### Survived、Pclass、Sexの関係の可視化
[seaborn.catplot](https://seaborn.pydata.org/generated/seaborn.catplot.html)を用います。
```Python
g = sns.catplot(x="Pclass",y="Survived", data=train, kind="bar")
g = g.set_ylabels("survival rate")
plt.show()
```

![スクリーンショット 2023-12-08 2.32.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569835/728854a6-c43f-ba00-9557-97e6a00b10ad.png)

Pclassが1、2のfemaleは、生存率が1に近いことがわかります。

# データ前処理
### trainとtestの連結
[pandas.concat](https://pandas.pydata.org/docs/reference/api/pandas.concat.html)を用いて、データフレームを結合します。
```Python
data = pd.concat([train, test], sort=False)
```

### 欠損値の確認
[pandas.isnull](https://pandas.pydata.org/docs/reference/api/pandas.isnull.html)、[pandas.DataFrame.sum](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.sum.html)を用いて、欠損値をカウントします。
```Python
data.isnull().sum()
```

### Sex
ラベルエンコーディングには[sklearn.preprocessing.LabelEncoder](https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.LabelEncoder.html)を用います。
```Python
from sklearn.preprocessing import LabelEncoder

le = LabelEncoder()
data['Sex'] = le.fit_transform(data['Sex'])
data.head()
```
femaleが0、maleが1となりました。

### Embarked
[pandas.DataFrame.fillna](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.fillna.html)を用いて欠損値をSで置換した後、ラベルエンコーディングを行います。
```Python
data['Embarked'].fillna(('S'), inplace=True)
data['Embarked'] = le.fit_transform(data['Embarked'])
data.head()
```
Cが0、Qが1、Sが2となりました。

### Fare
欠損値を平均値で置換します。
```Python
data['Fare'].fillna(np.mean(data['Fare']), inplace=True)
```
### Age
欠損値を中央値で置換します。
```Python
data['Age'].fillna(data['Age'].median(), inplace=True)
```

### Name、PassengerId、Ticket、Cabinの削除
データ分析に用いない列、Name、PassengerId、Ticket、Cabinを削除します。
```Python
delete_columns = ['Name', 'PassengerId', 'Ticket', 'Cabin']
data.drop(delete_columns, axis=1, inplace=True)
```

### 学習データとテストデータの抽出
```Python
train = data[:len(train)]
test = data[len(train):]
```
```Python
y_train = train['Survived']
X_train = train.drop('Survived', axis = 1)
X_test = test.drop('Survived', axis = 1)
```

# LightGBMで学習
[sklearn.model_selection.train_test_split](https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.train_test_split.html)を用いて、学習データを学習用、検証用に分割します。
パラメータのstratifyを指定することで、正解ラベルの割合をそろえることができます。
```Python
from sklearn.model_selection import train_test_split

X_train, X_valid, y_train, y_valid = train_test_split(X_train, y_train, test_size=0.3, random_state=0, stratify=y_train)
```
Pclass、Sex、Embarkedをカテゴリ変数として入力します。
カテゴリに順序性がない変数をカテゴリ変数として入力するのがよいそうです。
```Python
categorical_features = ['Pclass', 'Sex', 'Embarked']
```
[LightGBM](https://lightgbm.readthedocs.io/en/latest/Python-Intro.html)で学習、予測を行います。

```Python
import lightgbm as lgb

lgb_train = lgb.Dataset(X_train, y_train, categorical_feature=categorical_features)
lgb_eval = lgb.Dataset(X_valid, y_valid, reference=lgb_train, categorical_feature=categorical_features)

params = {
    'objective': 'binary'
}

model = lgb.train(
    params, lgb_train,
    valid_sets=[lgb_train, lgb_eval],
    verbose_eval=10,
    num_boost_round=1000,
    callbacks=[lgb.early_stopping(10)]
)

y_pred = model.predict(X_test, num_iteration=model.best_iteration)
```
予測結果を表示します。
```Python
y_pred[:10]
```
```
array([0.06799741, 0.53092879, 0.12402525, 0.10202349, 0.39770746,
       0.49337154, 0.70464621, 0.13773163, 0.68496324, 0.0487823 ])
```
0.5より大きい場合に1として、予測結果を再び表示します。
```Python
y_pred = (y_pred > 0.5).astype(int)
y_pred[:10]
```
```
array([0, 1, 0, 0, 0, 0, 1, 0, 1, 0])
```
予測結果が0または1になりました。

# 提出
提出データをsubmission.csvとして出力します。
```Python
sub = gender_submission
sub['Survived'] = list(map(int, y_pred))
sub.to_csv("submission.csv", index=False)
```

Public Scoreは0.76794でした。

学んだことを書きながら、データ分析スキルを上げることができました。
次は、LightGBMのパラメータやクロスバリデーションについて学びたいです。

# 参考文献
https://qiita.com/upura/items/3c10ff6fed4e7c3d70f0
https://www.kaggle.com/code/sishihara/upura-kaggle-tutorial-01-first-submission
https://ct-innovation01.xyz/DL-Freetime/kaggle-003/
https://qiita.com/kunishou/items/bd5fad9a334f4f5be51c
https://qiita.com/Maron_T/items/707ca62653a6d56cccbe
https://tebasakisan.hatenadiary.com/entry/2019/01/27/222102