Google Colabを学びたい Step9 Kaggleに挑戦

## はじめに
Google Colabを学びたい Step9です。そろそろ実際のデータを元に解析したいなと思いました！！
いい感じのデータを探してたところ、Kaggleのデータで挑戦してみたいと思います！！

## 🎓 データセット紹介：Students Performance in Exams

[Students Performance in Exams - Kaggle](https://www.kaggle.com/datasets/spscientist/students-performance-in-exams) は、教育関連のデータ分析を学ぶ上で非常に適した、シンプルかつ実用的なデータセットです。

### ✅ 概要

このデータセットは、1,000人の生徒に関する以下の情報を記録しています：

- 生徒の属性（性別・人種・親の学歴・昼食の種類・テスト対策の有無）
- 3つの科目（数学・読解・ライティング）の試験スコア（0〜100点）

### 📦 データの基本構成

| カラム名 | 説明 |
|----------|------|
| `gender` | 性別（`male` または `female`） |
| `race/ethnicity` | 人種・民族のグループ（Group A〜E） |
| `parental level of education` | 両親の最終学歴（例：`bachelor's degree`, `high school` など） |
| `lunch` | 昼食の種類（`standard` または `free/reduced`） |
| `test preparation course` | テスト対策コースの受講状況（`none` または `completed`） |
| `math score` | 数学のスコア（0〜100点） |
| `reading score` | 読解のスコア（0〜100点） |
| `writing score` | ライティングのスコア（0〜100点） |

### 💡 このデータでできる分析の例

- 各科目の平均点や得点分布の可視化（ヒストグラム・箱ひげ図）
- 性別・親の学歴・昼食の種類などによる成績の違い
- 科目間の相関関係（ヒートマップ）
- テスト対策コース受講者と非受講者の成績差
- 機械学習による得点予測モデルの構築（発展）

### 👍 初心者におすすめな理由

- カラム数が少なくてシンプル
- 欠損値・外れ値がなく、前処理がほとんど不要
- 教育という身近なテーマでイメージが湧きやすい
- 分類・回帰・可視化など、データ分析の基本をひととおり体験できる

---

本データセットは、PandasやSeabornを使ったデータ可視化の練習や、教師あり学習（回帰・分類）の入門教材として非常に人気があります。

https://www.kaggle.com/datasets/spscientist/students-performance-in-exams

## Hands-onスタート！！
まずは、対象のCSVをダウンロードし、GoogleDriveに保存しておきます！
その後、下記コマンドで実行

### CSVファイルの読み込み
```py:
from google.colab import drive
drive.mount('/content/drive')

import pandas as pd

# パスを明示
file_path = '/content/drive/MyDrive/Colab Notebooks/StudentsPerformance.csv'

# CSV読み込み
df = pd.read_csv(file_path)

# 表示
df.head()
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/1d8fd951-fbf6-4df0-a1a4-284149578ab9.png)

## データの分析を開始する
では解析をしていきましょう！！でも、何から分析していいのかがわからないというのが最初の壁です。
とりあえず、いくつかデータの中身を見てみたいと思います！！


### データの構造を見てみる
```py
# データ構造の確認（列名・型・nullの有無など）
df.info()
```

```shell:
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1000 entries, 0 to 999
Data columns (total 8 columns):
 #   Column                       Non-Null Count  Dtype 
---  ------                       --------------  ----- 
0   gender                       1000 non-null   object  ← 性別（文字列）、欠損なし
1   race/ethnicity               1000 non-null   object  ← 人種・民族グループ（文字列）、欠損なし
2   parental level of education  1000 non-null   object  ← 親の学歴（文字列）、欠損なし
3   lunch                        1000 non-null   object  ← 昼食の種類（標準 or 無料/割引）、欠損なし
4   test preparation course      1000 non-null   object  ← テスト対策を受けたか（文字列）、欠損なし
5   math score                   1000 non-null   int64   ← 数学の点数（整数）、欠損なし
6   reading score                1000 non-null   int64   ← 読解の点数（整数）、欠損なし
7   writing score                1000 non-null   int64   ← ライティングの点数（整数）、欠損なし
dtypes: int64(3), object(5)
memory usage: 62.6+ KB
```
:::note info
なるほどね。人種や親の学歴、数学やリーディング、ライティングの成績があるな。
で、なんなの？？昼食とか親の学歴も含まれているな。まぁ、いいか。こんなもんだな。
:::


### いくつかサンプルデータを見る
```py
# データの内容をざっと見る（先頭5行）
df.head()
```

```py:
index,gender,race/ethnicity,parental level of education,lunch,test preparation course,math score,reading score,writing score
0,female,group B,bachelor's degree,standard,none,72,72,74
1,female,group C,some college,standard,completed,69,90,88
2,female,group B,master's degree,standard,none,90,95,93
3,male,group A,associate's degree,free/reduced,none,47,57,44
4,male,group C,some college,standard,none,76,78,75
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/edf0d584-d96e-41d6-aaf8-556029674f1e.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/dd54cd2c-e6ea-4c9d-b7ce-73836c27b710.png)


## 数値の分析(平均・中央値・最大値)
```py
# 数値データの基本統計量（平均・中央値・最大値など）
df.describe()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/2d09961a-2c1a-4c76-ac71-44b3af693d0b.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/4ca6adf0-b1e5-44d5-9f07-cafeed97f83f.png)

:::note info
箱ひげ図にしてみよう！！表で読み込むより、図解されている方が読みやすいので！
:::

```py
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np

# フォント設定（日本語）
plt.rcParams['font.family'] = 'IPAexGothic'

# 日本語表示にするための変換辞書
subject_labels = {
    'math score': '数学',
    'reading score': '読解',
    'writing score': 'ライティング'
}

# 列を日本語化（コピー）
df_jp = df.rename(columns=subject_labels)
subjects = list(subject_labels.values())

# 平均値の計算
means = [df_jp[col].mean() for col in subjects]

# 箱ひげ図の描画
plt.figure(figsize=(8, 5))
ax = sns.boxplot(data=df_jp[subjects], palette="pastel")

# 平均値を赤丸で重ねる（位置は x=0,1,2...）
for i, mean in enumerate(means):
    ax.plot(i, mean, marker="o", color="red", label="平均" if i == 0 else "", markersize=8)

plt.title("教科ごとの点数分布（箱ひげ図＋平均）")
plt.ylabel("点数")
plt.grid(True)

# 凡例（最初の1回だけ表示）
plt.legend()
plt.show()
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/e2a6b2f2-9f72-4271-a810-3b24463231d8.png)

:::note info
全体的によく似たようなグラフで大きな差はないですね。
ただ、数学は下に外れ値が多く見える。数学の苦手な生徒が読解やライティングに比べると多い印象
:::

## 性別ごとの得点図の比較

```py
import matplotlib.pyplot as plt
import seaborn as sns

# フォント設定（日本語対応）
plt.rcParams['font.family'] = 'IPAexGothic'

# 教科ごとに箱ひげ図を描画
subjects = ['math score', 'reading score', 'writing score']
titles = ['数学の点数', '読解の点数', 'ライティングの点数']

for subject, title in zip(subjects, titles):
    plt.figure(figsize=(8, 5))
    ax = sns.boxplot(x='gender', y=subject, data=df, palette='pastel')

    # 平均値を赤丸で描く
    means = df.groupby('gender')[subject].mean()
    for i, gender in enumerate(means.index):
        ax.plot(i, means[gender], marker='o', color='red', label='平均' if i == 0 else "", markersize=8)

    plt.title(f"{title}（性別比較）")
    plt.ylabel("点数")
    plt.xlabel("性別")
    plt.grid(True)
    plt.legend()
    plt.show()
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/e3aaffee-c410-4b5a-9b3a-bd10c42b9f2b.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/f4309b5d-24ad-4c54-8144-2d56ae352e7e.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/5aba3f90-fc11-4d00-9a53-bd9d5bf36d19.png)

## 🎓 性別ごとの成績分析（箱ひげ図＋平均）

3教科（数学・読解・ライティング）の成績を、性別ごとに箱ひげ図と平均値マーカーで比較しました。  
その結果、それぞれの教科において性別による明確な傾向が見られました。

---

### 🟦 数学（Math）

- **男性の方が平均点・中央値ともに高い**
- 女性には極端に低いスコア（外れ値）が多く見られる
- 男性は分布が比較的安定しており、ばらつきも小さい

📌 **数学は男性がやや優位で、女性は苦手層が目立つ**

---

### 🟧 読解（Reading）

- **女性の方が平均点・中央値が高く、点数が安定**
- 男性はばらつきがあり、中央値もやや低い
- 女性の外れ値は少なく、高得点層に集中している印象

📌 **読解は女性がやや得意な傾向**

---

### 🟩 ライティング（Writing）

- **女性が圧倒的に優位**（平均・中央値が高く、安定している）
- 男性の方がばらつきが大きく、外れ値も多い

📌 **ライティングは女性の得意分野。非常に安定感がある**

---

## ✅ 総合的な考察

| 教科 | 優位な性別 | 備考 |
|------|------------|------|
| 数学 | 男性 | 平均点が高く、外れ値が少ない |
| 読解 | 女性 | 点数が安定していて高得点傾向 |
| ライティング | 女性 | 圧倒的に安定・高得点傾向あり |

---

## 💡 教育的示唆

- 女性に対しては**数学的支援**が有効
- 男性に対しては**言語力（読解・ライティング）の強化**が課題
- 教科ごとに**性別に応じたアプローチ**を取ることで、全体の底上げが期待できる


## 親の学歴別 × 教科別の成績分布

```py
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

# 日本語フォントを指定（Google Colab用）
plt.rcParams['font.family'] = 'IPAexGothic'

# 🔹 学歴の英語 → 日本語マッピング
edu_mapping = {
    "some high school": "高校中退",
    "high school": "高校卒業",
    "some college": "短大・大学中退",
    "associate's degree": "短大卒",
    "bachelor's degree": "大学卒",
    "master's degree": "大学院卒"
}

# 🔹 日本語順に並べるための順序リスト
edu_order_ja = [
    "高校中退",
    "高校卒業",
    "短大・大学中退",
    "短大卒",
    "大学卒",
    "大学院卒"
]

# 🔹 学歴の日本語ラベル列を作成
df['parent_education_ja'] = df['parental level of education'].map(edu_mapping)

# 🔹 教科と日本語タイトルの辞書
subjects = {
    'math score': '数学',
    'reading score': '読解',
    'writing score': 'ライティング'
}

# 🔹 各教科で箱ひげ図を表示（日本語学歴＋平均付き）
for subject, title in subjects.items():
    plt.figure(figsize=(10, 6))

    # 箱ひげ図（日本語順に並べて表示）
    ax = sns.boxplot(
        x='parent_education_ja',
        y=subject,
        data=df,
        order=edu_order_ja,
        palette='pastel'
    )

    # 平均値を赤い点でプロット
    means = df.groupby('parent_education_ja')[subject].mean()
    for i, label in enumerate(edu_order_ja):
        ax.plot(i, means[label], marker='o', color='red', label='平均' if i == 0 else "", markersize=8)

    plt.title(f"{title}の点数（親の学歴別）")
    plt.xlabel("親の学歴")
    plt.ylabel("点数")
    plt.xticks(rotation=20)
    plt.grid(True)
    plt.legend()
    plt.show()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/8ee77dc4-8c4d-4bdc-97e2-77873750681c.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/5bb6d4ca-7ef6-465e-a9cb-a44b52295848.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/f4495153-1abd-4d9e-9dbc-ce99f6d7408e.png)


## 📊 親の学歴と子どもの成績の関係（箱ひげ図による分析）

### 📝 分析の目的
この分析では、親の学歴ごとに子どもの点数（数学・読解・ライティング）の分布を箱ひげ図で可視化し、どのような傾向があるかを確認します。平均点も赤丸で重ねて表示しています。

---

### ✅ 考察ポイント

#### 1. 親の学歴が高いほど、子どもの成績も高い傾向がある
- 全ての教科において、**親の学歴が高いほど、平均点・中央値が高い傾向**が見られました。
- 特に**大学卒・大学院卒の親を持つ生徒のスコアが高い**傾向が一貫しています。

#### 2. 学歴が低い親の子どもは点数のばらつきが大きい
- **高校卒・高校中退の層では点数の分布が広く、ばらつきが大きい**傾向が見られます。
- 教育環境やサポートの個人差が大きく影響している可能性があります。

#### 3. 科目ごとの違い
| 教科     | 特徴                                                                 |
|----------|----------------------------------------------------------------------|
| 数学     | 学歴ごとの差が最も顕著。特に大学院卒の親を持つ生徒の得点が高い。       |
| 読解     | 全体的に得点が高く、親の学歴との相関も比較的明瞭。                     |
| ライティング | 読解に近い傾向だが、やや個人差（ばらつき）が多め。                     |


## 科目ごとの相関関係を見る

```py
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt

# 日本語フォント設定
plt.rcParams['font.family'] = 'IPAexGothic'

# 相関係数を計算（数値データだけ抽出）
score_df = df[['math score', 'reading score', 'writing score']]
corr = score_df.corr()

# 日本語のラベルを定義
score_df.columns = ['数学', '読解', 'ライティング']
corr.columns = ['数学', '読解', 'ライティング']
corr.index = ['数学', '読解', 'ライティング']

# ヒートマップを描画
plt.figure(figsize=(6, 5))
sns.heatmap(corr, annot=True, cmap='coolwarm', vmin=0, vmax=1, fmt='.2f')

plt.title('教科間の相関係数（ヒートマップ）')
plt.tight_layout()
plt.show()
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/47638870-5a59-480b-907c-5629d142ac8a.png)

## 最後に
簡単に分析できていいですね！！Google Colabで実際に分析をするのは初めてだったんですが、こんだけ簡単に分析できると色々夢が広がって楽しいですね！！！