STEP 38:実践プロジェクト1 – 探索的データ分析の可視化

🔬 STEP 38: 実践プロジェクト1 – 探索的データ分析の可視化

Kaggleのデータセットで、実践的なデータ分析をしよう!

📋 このステップで学ぶこと

  • 探索的データ分析(EDA)の概念と手順
  • Kaggleデータセットの入手方法
  • データの読み込みと基本確認
  • 仮説の立て方と検証方法
  • Seabornでの効率的な可視化
  • インサイトの発見と報告

🔬 1. 探索的データ分析(EDA)とは

EDAの目的と重要性

探索的データ分析(Exploratory Data Analysis, EDA)とは、データの特徴を理解し、パターンや異常を発見するためのプロセスです。

機械学習モデルを作る前や、レポートを作成する前に、まずデータを深く理解することが重要です。EDAを通じて「データは何を語っているのか」を読み解きます。

🎯 EDAの5つの目的
目的 具体的にやること 発見できること
1. 全体像の把握 サイズ、型、欠損値、範囲を確認 データの規模や品質の問題
2. パターンの発見 トレンド、季節性、相関関係を探る 変数間の関係性
3. 異常値の検出 外れ値やデータエラーを見つける データの信頼性の問題
4. 仮説の生成 「〇〇が△△に影響しているのでは?」 検証すべき問いの発見
5. 次のステップの決定 前処理の方針、モデル選択を考える 分析の方向性

EDAの標準的な手順

EDAには決まった手順があります。以下のステップに従うことで、漏れなくデータを探索できます。

【EDAの7ステップ】 STEP 1: データ読み込み ↓ CSVファイルを読み込み、最初の数行を確認 ↓ STEP 2: 基本統計量の確認 ↓ 平均、中央値、最大値、最小値などを確認 ↓ STEP 3: 欠損値・データ型の確認 ↓ どの列に欠損があるか、データ型は正しいか ↓ STEP 4: 分布の確認 ↓ ヒストグラム、箱ひげ図で各変数の分布を見る ↓ STEP 5: 相関関係の確認 ↓ 散布図、ヒートマップで変数間の関係を見る ↓ STEP 6: カテゴリ別の比較 ↓ グループごとに違いがあるか確認 ↓ STEP 7: インサイトのまとめ 発見したパターンや仮説を文書化
📊 EDAで使う主なグラフ
グラフ 用途 発見できること
ヒストグラム 1つの変数の分布を確認 偏り、ピーク、外れ値
箱ひげ図 外れ値と四分位数を確認 中央値、ばらつき、異常値
散布図 2つの変数の相関を確認 正/負の相関、クラスター
ヒートマップ 相関係数行列を可視化 多変数間の関係の全体像
ペアプロット 複数変数を一度に確認 すべての組み合わせの関係

📁 2. Kaggleデータセットの入手

Kaggleとは

Kaggleは、世界最大のデータサイエンスコミュニティです。無料で多様なデータセットが公開されており、実践的な分析スキルを磨くのに最適です。

今回使用するデータセット:タイタニック

今回の実践プロジェクトでは、Titanicデータセットを使用します。これはKaggleで最も有名なデータセットの1つで、1912年に沈没したタイタニック号の乗客データです。

【Titanicデータセットの概要】 ┌─────────────────────────────────────────────────────┐ │ 概要 │ ├─────────────────────────────────────────────────────┤ │ ・タイタニック号の乗客データ │ │ ・891名の乗客情報 │ │ ・生存/死亡の情報あり │ │ ・「誰が生き残ったか?」を分析 │ └─────────────────────────────────────────────────────┘ 【カラム(列)の説明】 ┌──────────────┬────────────────────────────────────┐ │ カラム名 │ 説明 │ ├──────────────┼────────────────────────────────────┤ │ PassengerId │ 乗客ID(連番) │ │ Survived │ 生存(1)/ 死亡(0) │ │ Pclass │ チケットクラス(1等/2等/3等) │ │ Name │ 名前 │ │ Sex │ 性別(male/female) │ │ Age │ 年齢 │ │ SibSp │ 同乗している兄弟/配偶者の数 │ │ Parch │ 同乗している親/子供の数 │ │ Ticket │ チケット番号 │ │ Fare │ 運賃(英ポンド) │ │ Cabin │ 客室番号 │ │ Embarked │ 乗船港(C=Cherbourg, Q=Queenstown, │ │ │ S=Southampton) │ └──────────────┴────────────────────────────────────┘ 【分析の焦点】 ・誰が生き残ったか?(性別、年齢、クラス等) ・生存率に影響を与えた要因は何か?

Google ColabでKaggleデータを読み込む方法

Kaggleからデータをダウンロードし、Google Colabで使用する方法を説明します。

# ======================================== # 方法1: Kaggle APIを使ってダウンロード # ======================================== # STEP 1: Kaggle APIキーの設定 # kaggle.com にログイン → Account → Create New API Token # → kaggle.json がダウンロードされる # STEP 2: Google Colabにkaggle.jsonをアップロード from google.colab import files files.upload() # kaggle.jsonを選択してアップロード # STEP 3: 認証情報を設定 !mkdir -p ~/.kaggle !cp kaggle.json ~/.kaggle/ !chmod 600 ~/.kaggle/kaggle.json # STEP 4: Titanicデータセットをダウンロード !kaggle competitions download -c titanic # STEP 5: ZIPを解凍 !unzip titanic.zip # STEP 6: データを読み込む import pandas as pd df = pd.read_csv(‘train.csv’) print(“データセット読み込み完了!”) print(f”行数: {len(df)}, 列数: {len(df.columns)}”)
💡 Kaggle APIを使わない簡単な方法

Kaggle APIの設定が難しい場合は、以下の方法でも可能です。

  1. Kaggleのウェブサイトからデータを手動でダウンロード
  2. Google Colabの左側「ファイル」タブにドラッグ&ドロップでアップロード
  3. pd.read_csv('train.csv')で読み込み

📊 3. データの読み込みと基本確認

ライブラリのインポートとデータ読み込み

まず必要なライブラリをインポートし、データを読み込みます。

# ステップ1: 必要なライブラリをインポート import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns # ステップ2: グラフの設定 plt.rcParams[‘font.sans-serif’] = [‘DejaVu Sans’] # フォント設定 plt.rcParams[‘axes.unicode_minus’] = False # マイナス記号の設定 # Seabornのスタイル設定 sns.set_style(“whitegrid”) # 背景を白いグリッドに sns.set_palette(“husl”) # カラーパレット # ステップ3: データを読み込む df = pd.read_csv(‘train.csv’) print(“=” * 50) print(“タイタニックデータセット読み込み完了!”) print(“=” * 50)

基本情報の確認

データを読み込んだら、まず基本的な情報を確認します。これがEDAの第一歩です。

# ======================================== # 基本情報の確認 # ======================================== # 1. 最初の5行を表示(データの雰囲気を掴む) print(“\n【最初の5行】”) print(df.head()) # 2. データの形状(行数と列数) print(f”\n【データサイズ】”) print(f”行数: {df.shape[0]}”) print(f”列数: {df.shape[1]}”) # 3. データ型と欠損値の確認 print(“\n【データ型と欠損値】”) print(df.info()) # 4. 基本統計量(数値列のみ) print(“\n【基本統計量】”) print(df.describe())
【データサイズ】 行数: 891 列数: 12 【基本統計量】(抜粋) Survived Pclass Age Fare count 891.000000 891.000000 714.000000 891.000000 mean 0.383838 2.308642 29.699118 32.204208 std 0.486592 0.836071 14.526497 49.693429 min 0.000000 1.000000 0.420000 0.000000 max 1.000000 3.000000 80.000000 512.329200

欠損値の確認と可視化

欠損値(データが入っていないセル)の確認は非常に重要です。どの列にどれだけ欠損があるかを把握しましょう。

# ======================================== # 欠損値の確認 # ======================================== # 欠損値の数 print(“【欠損値の数】”) print(df.isnull().sum()) # 欠損値の割合(%) print(“\n【欠損値の割合(%)】”) missing_percent = (df.isnull().sum() / len(df) * 100).round(2) print(missing_percent)
【欠損値の数】 PassengerId 0 Survived 0 Pclass 0 Name 0 Sex 0 Age 177 ← 19.9%が欠損 SibSp 0 Parch 0 Ticket 0 Fare 0 Cabin 687 ← 77.1%が欠損 Embarked 2 ← 0.2%が欠損
# ======================================== # 欠損値をヒートマップで可視化 # ======================================== plt.figure(figsize=(12, 6)) # 欠損値を1(欠損あり)、0(欠損なし)のヒートマップで表示 # 黄色のセルが欠損値を示す sns.heatmap(df.isnull(), cbar=True, yticklabels=False, cmap=’viridis’) plt.title(‘欠損値の分布(黄色 = 欠損)’, fontsize=16, fontweight=’bold’) plt.xlabel(‘カラム名’, fontsize=12) plt.tight_layout() plt.show() # 欠損値の多い列をまとめ print(“\n【欠損値の分析】”) print(“・Age(年齢): 177件(19.9%)欠損 → 平均値や中央値で補完可能”) print(“・Cabin(客室): 687件(77.1%)欠損 → 分析から除外を検討”) print(“・Embarked(乗船港): 2件(0.2%)欠損 → 最頻値で補完可能”)

🎯 4. 仮説の立て方と検証

EDAにおける仮説の重要性

EDAでは、ただグラフを作るだけでなく、「〇〇は△△に影響しているのでは?」という仮説を立て、それを検証することが重要です。

タイタニックのデータでは、「誰が生き残ったか」を分析します。以下の仮説を立てて検証してみましょう。

📝 今回検証する3つの仮説
仮説 根拠(予想) 検証方法
仮説1 女性と子供の生存率が高い(「女性と子供を優先」のルール) 性別・年齢ごとの生存率を比較
仮説2 チケットクラスが高いほど生存率が高い(富裕層は良い位置の客室) クラスごとの生存率を比較
仮説3 性別とクラスの組み合わせで効果が異なる クロス集計で確認

仮説1の検証: 性別と生存率

「女性と子供を優先」というルールが実践されたかを確認します。

# ======================================== # 仮説1: 性別と生存率の関係 # ======================================== # まず数値で確認 print(“【性別ごとの生存率】”) survival_by_sex = df.groupby(‘Sex’)[‘Survived’].mean() print(survival_by_sex) # 可視化 fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 5)) # ========== グラフ1: 性別ごとの生存率(棒グラフ) ========== survival_rate = df.groupby(‘Sex’)[‘Survived’].mean() * 100 # 棒グラフを作成 bars = ax1.bar([‘Female’, ‘Male’], survival_rate.values, color=[‘#E60012’, ‘#0068B7′]) # 値をグラフ上に表示 for bar, val in zip(bars, survival_rate.values): ax1.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 2, f'{val:.1f}%’, ha=’center’, fontsize=14, fontweight=’bold’) ax1.set_title(‘性別ごとの生存率’, fontsize=16, fontweight=’bold’) ax1.set_ylabel(‘生存率(%)’, fontsize=12) ax1.set_xlabel(‘性別’, fontsize=12) ax1.set_ylim(0, 100) ax1.grid(axis=’y’, alpha=0.3) # ========== グラフ2: 年齢分布と生存(ヒストグラム) ========== sns.histplot(data=df, x=’Age’, hue=’Survived’, multiple=’stack’, bins=30, ax=ax2, palette={0: ‘#E60012’, 1: ‘#009944’}) ax2.set_title(‘年齢分布と生存’, fontsize=16, fontweight=’bold’) ax2.set_xlabel(‘年齢’, fontsize=12) ax2.set_ylabel(‘人数’, fontsize=12) ax2.legend([‘死亡’, ‘生存’], title=’結果’) plt.tight_layout() plt.show() # 結論 print(“\n” + “=” * 50) print(“【仮説1の検証結果】”) print(“=” * 50) print(“✓ 女性の生存率: 約74%”) print(“✓ 男性の生存率: 約19%”) print(“→ 「女性と子供を優先」が実践されたことが確認できた”)

仮説2の検証: チケットクラスと生存率

富裕層(1等)の乗客は、3等の乗客より生存率が高いかを確認します。

# ======================================== # 仮説2: チケットクラスと生存率の関係 # ======================================== # 数値で確認 print(“【チケットクラスごとの生存率】”) survival_by_class = df.groupby(‘Pclass’)[‘Survived’].mean() print(survival_by_class) # 可視化 fig, ax = plt.subplots(figsize=(10, 6)) # クロス集計(クラスごとの生存/死亡の人数) survival_cross = pd.crosstab(df[‘Pclass’], df[‘Survived’], normalize=’index’) * 100 # 積み上げ棒グラフを作成 survival_cross.plot(kind=’bar’, ax=ax, color=[‘#E60012’, ‘#009944’], stacked=True, width=0.7) ax.set_title(‘チケットクラスごとの生存率’, fontsize=16, fontweight=’bold’) ax.set_ylabel(‘割合(%)’, fontsize=12) ax.set_xlabel(‘チケットクラス’, fontsize=12) ax.set_xticklabels([‘1等(高級)’, ‘2等(中級)’, ‘3等(一般)’], rotation=0) ax.legend([‘死亡’, ‘生存’], title=’結果’, loc=’upper right’) ax.grid(axis=’y’, alpha=0.3) # 各クラスの生存率を表示 for i, (idx, row) in enumerate(survival_cross.iterrows()): ax.text(i, row[1]/2, f'{row[1]:.1f}%’, ha=’center’, va=’center’, fontsize=12, fontweight=’bold’, color=’white’) plt.tight_layout() plt.show() # 結論 print(“\n” + “=” * 50) print(“【仮説2の検証結果】”) print(“=” * 50) print(“✓ 1等の生存率: 約63%”) print(“✓ 2等の生存率: 約47%”) print(“✓ 3等の生存率: 約24%”) print(“→ チケットクラスが高いほど生存率が高い”)

仮説3の検証: 性別×クラスの組み合わせ効果

性別とクラスを組み合わせたとき、どのような傾向が見えるか確認します。

# ======================================== # 仮説3: 性別×クラスの組み合わせ効果 # ======================================== # 数値で確認 print(“【性別×クラスの生存率】”) cross_survival = df.groupby([‘Pclass’, ‘Sex’])[‘Survived’].mean() print(cross_survival) # 可視化 fig, ax = plt.subplots(figsize=(10, 6)) # Seabornの棒グラフで性別×クラスを表示 sns.barplot(data=df, x=’Pclass’, y=’Survived’, hue=’Sex’, ax=ax, palette={‘male’: ‘#0068B7’, ‘female’: ‘#E60012’}, errorbar=None) # エラーバーを非表示 ax.set_title(‘チケットクラスと性別ごとの生存率’, fontsize=16, fontweight=’bold’) ax.set_ylabel(‘生存率’, fontsize=12) ax.set_xlabel(‘チケットクラス’, fontsize=12) ax.set_xticklabels([‘1等’, ‘2等’, ‘3等’]) ax.legend(title=’性別’, labels=[‘男性’, ‘女性’]) ax.grid(axis=’y’, alpha=0.3) # Y軸を0-1の範囲に設定 ax.set_ylim(0, 1) plt.tight_layout() plt.show() # 結論 print(“\n” + “=” * 50) print(“【仮説3の検証結果】”) print(“=” * 50) print(“✓ 1等女性の生存率: 約96%(最も高い)”) print(“✓ 3等男性の生存率: 約14%(最も低い)”) print(“→ すべてのクラスで女性の生存率が高い”) print(“→ 性別とクラスの両方が生存に影響している”)

🔍 5. Seabornでの効率的な探索

ペアプロットで全体像を一度に把握

ペアプロットは、複数の変数の関係を一度に可視化できる強力なツールです。すべての数値変数の組み合わせについて、散布図と分布を同時に確認できます。

# ======================================== # ペアプロットで複数変数を一度に確認 # ======================================== # 分析に使う数値変数を選択 numerical_cols = [‘Age’, ‘SibSp’, ‘Parch’, ‘Fare’] # 欠損値を除去したデータを準備 df_clean = df[numerical_cols + [‘Survived’]].dropna() # ペアプロットを作成 # hue=’Survived’で生存/死亡で色分け # diag_kind=’kde’で対角線にカーネル密度推定を表示 g = sns.pairplot(df_clean, hue=’Survived’, palette={0: ‘#E60012’, 1: ‘#009944′}, diag_kind=’kde’, height=2.5, plot_kws={‘alpha’: 0.6}) # タイトルを追加 g.figure.suptitle(‘主要変数のペアプロット(生存別)’, y=1.02, fontsize=16, fontweight=’bold’) plt.tight_layout() plt.show() # 読み取れること print(“\n【ペアプロットから読み取れること】”) print(“・運賃(Fare)が高いほど生存率が高い傾向”) print(“・年齢(Age)は幅広く分布、特定の年齢層に偏りなし”) print(“・SibSp, Parchは0の人が多い(単独乗船が多数)”)

相関ヒートマップで関係性を把握

相関ヒートマップは、すべての数値変数間の相関係数を色で表現します。どの変数が生存と関係しているかが一目でわかります。

# ======================================== # 相関ヒートマップ # ======================================== # 相関係数行列を計算 # 分析に使う数値変数を選択 cols_for_corr = [‘Survived’, ‘Pclass’, ‘Age’, ‘SibSp’, ‘Parch’, ‘Fare’] correlation = df[cols_for_corr].corr() # ヒートマップで可視化 plt.figure(figsize=(10, 8)) # annot=True で数値を表示 # fmt=’.2f’ で小数点以下2桁 # center=0 で0を中心に色分け sns.heatmap(correlation, annot=True, fmt=’.2f’, cmap=’coolwarm’, center=0, square=True, linewidths=1, cbar_kws={“shrink”: 0.8}) plt.title(‘相関係数ヒートマップ’, fontsize=16, fontweight=’bold’, pad=20) plt.tight_layout() plt.show() # 主な発見 print(“\n【相関ヒートマップから読み取れること】”) print(“・Survived と Pclass: -0.34(負の相関)”) print(” → クラスが低い(3等)ほど生存率が低い”) print(“・Survived と Fare: 0.26(正の相関)”) print(” → 運賃が高いほど生存率が高い”) print(“・Pclass と Fare: -0.55(負の相関)”) print(” → 当然だが、1等は運賃が高い”)

箱ひげ図で外れ値を検出

箱ひげ図は、データの分布と外れ値を同時に確認できます。異常に高い運賃や極端な年齢を検出しましょう。

# ======================================== # 箱ひげ図で外れ値を検出 # ======================================== fig, axes = plt.subplots(2, 2, figsize=(14, 10)) # Age(年齢) sns.boxplot(data=df, y=’Age’, ax=axes[0, 0], color=’#0068B7′) axes[0, 0].set_title(‘年齢の分布’, fontsize=14, fontweight=’bold’) axes[0, 0].set_ylabel(‘年齢’, fontsize=12) # Fare(運賃) sns.boxplot(data=df, y=’Fare’, ax=axes[0, 1], color=’#009944′) axes[0, 1].set_title(‘運賃の分布’, fontsize=14, fontweight=’bold’) axes[0, 1].set_ylabel(‘運賃(ポンド)’, fontsize=12) # SibSp(兄弟/配偶者) sns.boxplot(data=df, y=’SibSp’, ax=axes[1, 0], color=’#F39800′) axes[1, 0].set_title(‘兄弟/配偶者の数’, fontsize=14, fontweight=’bold’) axes[1, 0].set_ylabel(‘人数’, fontsize=12) # Parch(親/子供) sns.boxplot(data=df, y=’Parch’, ax=axes[1, 1], color=’#E60012′) axes[1, 1].set_title(‘親/子供の数’, fontsize=14, fontweight=’bold’) axes[1, 1].set_ylabel(‘人数’, fontsize=12) plt.tight_layout() plt.show() # 外れ値の分析 print(“\n【外れ値の発見】”) print(f”・Fare: 最高額は {df[‘Fare’].max():.2f}ポンド(VIP客?)”) print(f”・Age: 最高齢は {df[‘Age’].max():.0f}歳”) print(f”・SibSp: 最大 {df[‘SibSp’].max()}人の兄弟/配偶者と乗船”) print(f”・Parch: 最大 {df[‘Parch’].max()}人の親/子供と乗船”)

📝 6. インサイトのまとめと総合レポート

発見したパターンのまとめ

ここまでの分析で発見したパターンを整理します。これがEDAの最終成果物となります。

【タイタニックデータ分析のインサイト】 🔍 主な発見: ┌─────────────────────────────────────────────────────────────┐ │ 1. 性別の影響(最も強い要因) │ ├─────────────────────────────────────────────────────────────┤ │ ✓ 女性の生存率: 74% │ │ ✓ 男性の生存率: 19% │ │ → 「女性と子供を優先」が実践された │ └─────────────────────────────────────────────────────────────┘ ┌─────────────────────────────────────────────────────────────┐ │ 2. チケットクラスの影響 │ ├─────────────────────────────────────────────────────────────┤ │ ✓ 1等の生存率: 63% │ │ ✓ 2等の生存率: 47% │ │ ✓ 3等の生存率: 24% │ │ → 富裕層ほど生存率が高い(客室の位置が影響?) │ └─────────────────────────────────────────────────────────────┘ ┌─────────────────────────────────────────────────────────────┐ │ 3. 年齢の影響 │ ├─────────────────────────────────────────────────────────────┤ │ ✓ 子供(0-10歳)の生存率: 約61% │ │ ✓ 高齢者(60歳以上)の生存率: 約22% │ │ → 子供は優先されたが、高齢者は低い │ └─────────────────────────────────────────────────────────────┘ ┌─────────────────────────────────────────────────────────────┐ │ 4. 運賃の影響 │ ├─────────────────────────────────────────────────────────────┤ │ ✓ 運賃と生存率に正の相関(r = 0.26) │ │ → 高額チケット = 良い客室 = 脱出しやすい位置 │ └─────────────────────────────────────────────────────────────┘ 📊 データ品質の問題: ・Age(年齢): 19.9%が欠損 → 補完が必要 ・Cabin(客室番号): 77.1%が欠損 → 分析から除外を検討 ・Embarked(乗船港): 0.2%が欠損 → 最頻値で補完可能

総合レポートの作成

最後に、発見したすべてのインサイトを1つの総合グラフにまとめます。これがEDAの最終成果物です。

# ======================================== # 総合レポート(9つのグラフを1つにまとめる) # ======================================== fig = plt.figure(figsize=(16, 12)) # ========== 1. 全体の生存率(円グラフ) ========== ax1 = plt.subplot(3, 3, 1) survival_counts = df[‘Survived’].value_counts() colors = [‘#E60012’, ‘#009944’] ax1.pie(survival_counts, labels=[‘死亡’, ‘生存’], autopct=’%1.1f%%’, colors=colors, startangle=90) ax1.set_title(‘全体の生存率’, fontweight=’bold’) # ========== 2. 性別と生存 ========== ax2 = plt.subplot(3, 3, 2) sns.countplot(data=df, x=’Sex’, hue=’Survived’, ax=ax2, palette={0: ‘#E60012’, 1: ‘#009944’}) ax2.set_title(‘性別ごとの生存’, fontweight=’bold’) ax2.set_xticklabels([‘女性’, ‘男性’]) ax2.legend([‘死亡’, ‘生存’]) # ========== 3. クラスと生存 ========== ax3 = plt.subplot(3, 3, 3) sns.countplot(data=df, x=’Pclass’, hue=’Survived’, ax=ax3, palette={0: ‘#E60012’, 1: ‘#009944’}) ax3.set_title(‘クラスごとの生存’, fontweight=’bold’) ax3.set_xticklabels([‘1等’, ‘2等’, ‘3等’]) ax3.legend([‘死亡’, ‘生存’]) # ========== 4. 年齢分布 ========== ax4 = plt.subplot(3, 3, 4) sns.histplot(data=df, x=’Age’, kde=True, ax=ax4, color=’#0068B7′) ax4.set_title(‘年齢分布’, fontweight=’bold’) # ========== 5. 運賃分布 ========== ax5 = plt.subplot(3, 3, 5) sns.histplot(data=df, x=’Fare’, kde=True, ax=ax5, color=’#009944′) ax5.set_title(‘運賃分布’, fontweight=’bold’) # ========== 6. クラス×性別の生存率 ========== ax6 = plt.subplot(3, 3, 6) sns.barplot(data=df, x=’Pclass’, y=’Survived’, hue=’Sex’, ax=ax6, errorbar=None) ax6.set_title(‘クラス×性別の生存率’, fontweight=’bold’) ax6.set_xticklabels([‘1等’, ‘2等’, ‘3等’]) # ========== 7. 家族サイズと生存率 ========== ax7 = plt.subplot(3, 3, 7) df[‘FamilySize’] = df[‘SibSp’] + df[‘Parch’] + 1 # 家族サイズを計算 sns.barplot(data=df, x=’FamilySize’, y=’Survived’, ax=ax7, color=’#F39800′, errorbar=None) ax7.set_title(‘家族サイズと生存率’, fontweight=’bold’) ax7.set_xlabel(‘家族サイズ’) # ========== 8. 乗船港と生存 ========== ax8 = plt.subplot(3, 3, 8) sns.countplot(data=df, x=’Embarked’, hue=’Survived’, ax=ax8, palette={0: ‘#E60012’, 1: ‘#009944’}) ax8.set_title(‘乗船港ごとの生存’, fontweight=’bold’) ax8.legend([‘死亡’, ‘生存’]) # ========== 9. 年齢と運賃の散布図 ========== ax9 = plt.subplot(3, 3, 9) sns.scatterplot(data=df, x=’Age’, y=’Fare’, hue=’Survived’, ax=ax9, palette={0: ‘#E60012’, 1: ‘#009944’}, alpha=0.6) ax9.set_title(‘年齢と運賃(生存別)’, fontweight=’bold’) ax9.legend([‘死亡’, ‘生存’]) # 全体タイトル plt.suptitle(‘タイタニック号 探索的データ分析 – 総合レポート’, fontsize=18, fontweight=’bold’, y=0.995) plt.tight_layout() plt.show() print(“\n” + “=” * 50) print(“📊 探索的データ分析 完了!”) print(“=” * 50) print(“主要な発見を上記のグラフにまとめました。”)

📝 STEP 38 のまとめ

✅ このステップで学んだこと
トピック 重要ポイント
EDAとは データの特徴を理解し、パターンや異常を発見するプロセス
EDAの手順 読み込み→基本統計→欠損値確認→分布→相関→カテゴリ比較→まとめ
仮説検証 「〇〇は△△に影響しているのでは?」→ グラフで検証
Seabornの活用 ペアプロット、ヒートマップ、箱ひげ図で効率的に探索
インサイト 発見したパターンを言語化し、文書にまとめる
総合レポート 複数のグラフを1つにまとめて全体像を示す
💡 最重要ポイント

探索的データ分析(EDA)は、データサイエンスの最も重要なステップです。モデルを作る前に、まずデータを深く理解することが成功への鍵です。

  • 仮説を立て、グラフで検証するサイクルを繰り返す
  • 「なぜ?」と問い続けることが優れた分析者への道
  • Seabornを使うことで、効率的に多様なグラフを作成できる

次のステップでは、実践プロジェクト2として経営ダッシュボードを作成します!

📝 実践演習

演習 1 基礎

Titanicデータで、乗船港(Embarked)ごとの生存率を計算し、棒グラフで可視化してください。

【解答コード】
# 乗船港ごとの生存率を計算 print(“【乗船港ごとの生存率】”) print(df.groupby(‘Embarked’)[‘Survived’].mean()) # 可視化 plt.figure(figsize=(8, 5)) sns.barplot(data=df, x=’Embarked’, y=’Survived’, palette=’Set2′, errorbar=None) plt.title(‘乗船港ごとの生存率’, fontsize=14, fontweight=’bold’) plt.xlabel(‘乗船港’) plt.ylabel(‘生存率’) plt.show() # C=Cherbourg: 55%, Q=Queenstown: 39%, S=Southampton: 34%

ポイント:Cherbourg(C)からの乗客は生存率が高い。これは1等の乗客が多かったためと考えられます。

演習 2 応用

「家族サイズ(SibSp + Parch + 1)と生存率の関係」について仮説を立て、検証してください。

【解答コード】
# 仮説: 適度な家族サイズ(2-4人)が最も生存率が高い # 家族サイズを計算 df[‘FamilySize’] = df[‘SibSp’] + df[‘Parch’] + 1 # 家族サイズごとの生存率 print(“【家族サイズごとの生存率】”) print(df.groupby(‘FamilySize’)[‘Survived’].mean()) # 可視化 plt.figure(figsize=(10, 6)) sns.barplot(data=df, x=’FamilySize’, y=’Survived’, palette=’Blues_d’, errorbar=None) plt.title(‘家族サイズと生存率’, fontsize=14, fontweight=’bold’) plt.xlabel(‘家族サイズ’) plt.ylabel(‘生存率’) plt.axhline(y=df[‘Survived’].mean(), color=’red’, linestyle=’–‘, label=’全体平均’) plt.legend() plt.show() # 結論: 家族サイズ2-4人が最も生存率が高い # 単独(1人)や大家族(5人以上)は生存率が低い

結論:2〜4人の家族が最も生存率が高い。単独乗船者は助け合う相手がおらず、大家族は全員を救うのが難しかったと推測されます。

演習 3 発展

別のKaggleデータセット(Iris, House Prices等)をダウンロードし、同様のEDAを実施してください。

【Irisデータセットを使った例】
# Irisデータセット(scikit-learnに組み込み) from sklearn.datasets import load_iris import pandas as pd import seaborn as sns # データ読み込み iris = load_iris() df_iris = pd.DataFrame(iris.data, columns=iris.feature_names) df_iris[‘species’] = iris.target # 基本確認 print(“【基本情報】”) print(df_iris.info()) print(df_iris.describe()) # ペアプロット sns.pairplot(df_iris, hue=’species’, palette=’Set2′) plt.suptitle(‘Iris Dataset – ペアプロット’, y=1.02) plt.show() # 相関ヒートマップ plt.figure(figsize=(8, 6)) sns.heatmap(df_iris.corr(), annot=True, cmap=’coolwarm’) plt.title(‘Iris Dataset – 相関ヒートマップ’) plt.show()

❓ よくある質問

Q1: EDAに決まった手順はありますか?
基本的な流れはありますが、柔軟に対応しましょう。一般的には、データ読み込み→基本統計→欠損値確認→分布確認→相関確認→カテゴリ別比較の順です。ただし、データや目的によって優先順位は変わります。重要なのは「すべての変数を確認する」ことです。
Q2: すべてのグラフを作る必要がありますか?
いいえ、目的に応じて選択しましょう。最初は多めにグラフを作り、重要な発見があったものを残します。最終レポートには、インサイトを伝えるために本当に必要なグラフだけを含めます。「このグラフは何を伝えたいのか?」を常に考えましょう。
Q3: 相関係数はどれくらいが「強い」ですか?
一般的な目安は以下の通りです。 |r| > 0.7: 強い相関、 0.4 < |r| < 0.7: 中程度の相関、 |r| < 0.4: 弱い相関。 ただし、分野や文脈によって解釈は異なります。また、相関は因果関係を示すわけではないことに注意してください。
Q4: 欠損値はどう処理すべきですか?
欠損の割合と理由によって対応が変わります。 少ない場合(<5%): 平均値、中央値、最頻値で補完。 中程度(5-30%): 予測モデルで補完、または欠損自体を特徴量に。 多い場合(>30%): その列を分析から除外することを検討。 重要なのは「なぜ欠損しているか」を考えることです。
Q5: EDAにどれくらい時間をかけるべきですか?
プロジェクト全体の20-30%が目安です。「早くモデルを作りたい」という気持ちはわかりますが、EDAを疎かにすると後で問題が発生します。データを深く理解してから次のステップに進むことで、結果的に時間を節約できます。
📝

学習メモ

データ可視化マスター - Step 38

📋 過去のメモ一覧
#artnasekai #学習メモ
LINE