Seabornで高速データサイエンス実装レシピ
はじめに
はじめまして、株式会社dotConfでAIエンジニアをしている古菅です!

データサイエンスの現場では、「データの理解」 が成功の鍵を握ります。しかし、分析に着手する前にデータの性質を把握する探索的データ解析(EDA) は、意外と時間がかかるものです。
今回は、Pythonの強力な可視化ライブラリSeabornを使い、煩雑なコードを書かずに高速で本質的なデータ理解を実現する「実装レシピ」を紹介します。初学者の方には分かりやすく、実務者の方には「あのグラフが一瞬で書けるのか!」という発見を提供します。
なぜSeabornを選ぶのか?
Pythonの可視化ライブラリといえばMatplotlibが基本ですが、なぜデータサイエンスの現場ではSeabornが選ばれることが多いのでしょうか?
それは、「少ないコードでより深い洞察を得られる」、つまり高速なデータ探索に適しているからです。
Matplotlib vs Seaborn
| 特徴 | Matplotlib | Seaborn |
|---|---|---|
| レベル | 低水準API (Low-Level) | 高水準API (High-Level) |
| 用途 | グラフの細かい調整、論文向け、基礎 | データ分析・統計可視化、高速なEDA |
| 記述量 | 多い(軸設定、凡例設定など) | 少ない(データと列名指定のみ) |
| デザイン | シンプル、カスタマイズ必須 | デフォルトで洗練、統計的な意味合いを持つ |
Seabornは、統計的な概念(分布、相関、カテゴリ比較)を最初から考慮した関数を提供しているため、「データサイエンスの文脈でよくあるグラフ」 を一行で描画できます。これが 「高速化」 の正体です。
環境構築(5分で完了)
今回は、Pythonの定番ライブラリのみを使用します。
ステップ1: 必要なライブラリのインストール
pip install pandas numpy matplotlib seaborn scikit-learn
ステップ2: ライブラリのインポートとデータ準備
# ライブラリのインポート
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import warnings
# 警告を非表示(見やすくするため)
warnings.filterwarnings('ignore')
# グラフ表示の設定
plt.rcParams['figure.figsize'] = (10, 6)
plt.rcParams['figure.dpi'] = 100
plt.rcParams['font.size'] = 11
# Seabornのスタイル設定
sns.set_style("whitegrid")
sns.set_palette("husl")
print("ライブラリの読み込み完了!")
ステップ3: サンプルデータの読み込みと確認
# タイタニックデータセットの読み込み
df = sns.load_dataset('titanic')
# データの基本情報を確認
print("=== データセットの基本情報 ===")
print(f"データ件数: {len(df)}行")
print(f"列数: {len(df.columns)}列\n")
# 最初の5行を表示
print("=== データの最初の5行 ===")
print(df.head())
# データ型と欠損値の確認
print("\n=== 各列のデータ型と欠損値 ===")
print(df.info())
# 基本統計量
print("\n=== 数値列の基本統計量 ===")
print(df.describe())
実行結果(クリックして展開)
=== データセットの基本情報 ===
データ件数: 891行
列数: 15列
=== データの最初の5行 ===
survived pclass sex age sibsp parch fare embarked class who adult_male deck embark_town alive alone
0 0 3 male 22.0 1 0 7.2500 S Third man True NaN Southampton no False
1 1 1 female 38.0 1 0 71.2833 C First woman False C Cherbourg yes False
2 1 3 female 26.0 0 0 7.9250 S Third woman False NaN Southampton yes True
3 1 1 female 35.0 1 0 53.1000 S First woman False C Southampton yes False
4 0 3 male 35.0 0 0 8.0500 S Third man True NaN Southampton no True
=== 各列のデータ型と欠損値 ===
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 891 entries, 0 to 890
Data columns (total 15 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 survived 891 non-null int64
1 pclass 891 non-null int64
2 sex 891 non-null object
3 age 714 non-null float64
4 sibsp 891 non-null int64
5 parch 891 non-null int64
6 fare 891 non-null float64
7 embarked 889 non-null object
8 class 891 non-null category
9 who 891 non-null object
10 adult_male 891 non-null bool
11 deck 203 non-null category
12 embark_town 889 non-null object
13 alive 891 non-null object
14 alone 891 non-null bool
dtypes: bool(2), category(2), float64(2), int64(4), object(5)
memory usage: 80.7+ KB
=== 数値列の基本統計量 ===
survived pclass age sibsp parch fare
count 891.000000 891.000000 714.000000 891.000000 891.000000 891.000000
mean 0.383838 2.308642 29.699118 0.523008 0.381594 32.204208
std 0.486592 0.836071 14.526497 1.102743 0.806057 49.693429
min 0.000000 1.000000 0.420000 0.000000 0.000000 0.000000
25% 0.000000 2.000000 20.125000 0.000000 0.000000 7.910400
50% 0.000000 3.000000 28.000000 0.000000 0.000000 14.454200
75% 1.000000 3.000000 38.000000 1.000000 0.000000 31.000000
max 1.000000 3.000000 80.000000 8.000000 6.000000 512.329200
実装レシピ1:データの分布を高速で把握
1-1. 単一変数の頻度と分布(histplot)
数値データがどのような値を中心に、どのようにバラついているかを瞬時に把握します。
# 乗客の年齢(age)の分布
plt.figure(figsize=(12, 5))
# 左側: 生存/死亡別の年齢分布
plt.subplot(1, 2, 1)
sns.histplot(
data=df,
x='age',
kde=True, # カーネル密度推定(滑らかな線)を追加
hue='survived', # 生存/死亡で色分け
palette='viridis',
bins=30
)
plt.title('Age Distribution by Survival Status', fontsize=14, fontweight='bold')
plt.xlabel('Age', fontsize=12)
plt.ylabel('Count', fontsize=12)
plt.legend(title='Survived', labels=['No', 'Yes'])
# 右側: 性別での年齢分布
plt.subplot(1, 2, 2)
sns.histplot(
data=df,
x='age',
kde=True,
hue='sex',
palette='Set2',
bins=30
)
plt.title('Age Distribution by Sex', fontsize=14, fontweight='bold')
plt.xlabel('Age', fontsize=12)
plt.ylabel('Count', fontsize=12)
plt.tight_layout()
plt.savefig('01_histplot.png', dpi=150, bbox_inches='tight')
plt.show()
print("グラフを保存しました: 01_histplot.png")
実行結果(クリックして展開)

左のグラフからは、20-40歳の乗客が多く、生存者は若年層に多い傾向が見られます。右のグラフでは、男女の年齢分布はほぼ同様であることがわかります。
1-2. 統計的な滑らかな分布(kdeplot)
データがどこに集中しているかを確率密度で滑らかに表現し、グループ間の比較を際立たせます。
# 運賃(fare)の分布比較
plt.figure(figsize=(12, 5))
# 左側: 客室等級別の運賃分布
plt.subplot(1, 2, 1)
sns.kdeplot(
data=df,
x='fare',
hue='pclass', # 客室等級(1, 2, 3等)で色分け
fill=True,
alpha=.5,
palette='Set1',
common_norm=False
)
plt.title('Fare Distribution by Pclass', fontsize=14, fontweight='bold')
plt.xlabel('Fare', fontsize=12)
plt.ylabel('Density', fontsize=12)
plt.xlim(0, 300) # 見やすくするため上限を設定
# 右側: 生存状況別の運賃分布
plt.subplot(1, 2, 2)
sns.kdeplot(
data=df,
x='fare',
hue='survived',
fill=True,
alpha=.5,
palette='coolwarm',
common_norm=False
)
plt.title('Fare Distribution by Survival', fontsize=14, fontweight='bold')
plt.xlabel('Fare', fontsize=12)
plt.ylabel('Density', fontsize=12)
plt.xlim(0, 300)
plt.legend(title='Survived', labels=['No', 'Yes'])
plt.tight_layout()
plt.savefig('02_kdeplot.png', dpi=150, bbox_inches='tight')
plt.show()
print("グラフを保存しました: 02_kdeplot.png")
実行結果(クリックして展開)

1等客室は高額な運賃に集中し、3等客室は低額に集中していることが明確です。生存者は相対的に高額の運賃を支払った乗客に多い傾向が見られます。
実装レシピ2:2変量の関係性を一発で可視化
2-1. 散布図と回帰直線の同時描画(regplot)
2つの数値データの間に相関があるかを、散布図と同時に信頼区間付きの回帰直線で確認します。
# 運賃(fare)と年齢(age)の関係
plt.figure(figsize=(12, 5))
# 左側: 全データでの回帰分析
plt.subplot(1, 2, 1)
sns.regplot(
data=df,
x='age',
y='fare',
ci=95, # 95%信頼区間を表示
scatter_kws={'alpha': 0.3, 's': 30},
line_kws={'color': 'red', 'linewidth': 2}
)
plt.title('Age vs Fare with Regression Line', fontsize=14, fontweight='bold')
plt.xlabel('Age', fontsize=12)
plt.ylabel('Fare', fontsize=12)
plt.ylim(0, 300)
# 右側: 客室等級別の関係
plt.subplot(1, 2, 2)
for pclass in [1, 2, 3]:
subset = df[df['pclass'] == pclass]
plt.scatter(subset['age'], subset['fare'], alpha=0.4, label=f'Class {pclass}', s=30)
plt.title('Age vs Fare by Pclass', fontsize=14, fontweight='bold')
plt.xlabel('Age', fontsize=12)
plt.ylabel('Fare', fontsize=12)
plt.legend(title='Pclass')
plt.ylim(0, 300)
plt.tight_layout()
plt.savefig('03_regplot.png', dpi=150, bbox_inches='tight')
plt.show()
print("グラフを保存しました: 03_regplot.png")
実行結果(クリックして展開)

年齢と運賃の間に強い相関は見られませんが、客室等級によって運賃の範囲が大きく異なることが確認できます。
2-2. 散布図と周辺分布の同時確認(jointplot)
散布図だけでなく、それぞれの軸の周辺にヒストグラムや密度曲線を同時に描画します。2つの変数の関係性とそのデータの偏りを1行で確認できる、EDAに必須の関数です。
# 年齢と運賃の関係 + 周辺分布
g = sns.jointplot(
data=df,
x='age',
y='fare',
kind='hex', # データの集中度を六角形で表現
height=8,
ratio=4,
marginal_kws=dict(bins=30, fill=True)
)
g.fig.suptitle('Age & Fare Relationship with Marginal Distribution',
y=1.02, fontsize=14, fontweight='bold')
g.set_axis_labels('Age', 'Fare', fontsize=12)
plt.savefig('04_jointplot_hex.png', dpi=150, bbox_inches='tight')
plt.show()
# 別パターン: 散布図バージョン
g2 = sns.jointplot(
data=df,
x='age',
y='fare',
kind='scatter',
hue='survived',
palette='viridis',
height=8,
ratio=4,
alpha=0.5
)
g2.fig.suptitle('Age & Fare by Survival Status',
y=1.02, fontsize=14, fontweight='bold')
g2.set_axis_labels('Age', 'Fare', fontsize=12)
plt.savefig('04_jointplot_scatter.png', dpi=150, bbox_inches='tight')
plt.show()
print("グラフを保存しました: 04_jointplot_hex.png, 04_jointplot_scatter.png")
実行結果(クリックして展開)


周辺分布を見ると、運賃は低額に偏っており、年齢は20-40歳に集中していることがわかります。散布図からは、高額運賃の乗客に生存者が多い傾向が見られます。
実装レシピ3:カテゴリ別集計を美しく表現
実務では、あるカテゴリ(性別、地域など)によって数値データに違いがあるかを検証することが非常に多いです。
3-1. カテゴリ別の分布(boxplotとviolinplot)
# 客室等級(pclass)ごとの年齢(age)分布
fig, axes = plt.subplots(2, 2, figsize=(14, 10))
# 左上:箱ひげ図(pclass別)
sns.boxplot(data=df, x='pclass', y='age', palette='Pastel1', ax=axes[0, 0])
axes[0, 0].set_title('Box Plot - Age by Pclass', fontsize=13, fontweight='bold')
axes[0, 0].set_xlabel('Pclass', fontsize=11)
axes[0, 0].set_ylabel('Age', fontsize=11)
# 右上:バイオリンプロット(pclass別)
sns.violinplot(data=df, x='pclass', y='age', palette='Pastel2', ax=axes[0, 1])
axes[0, 1].set_title('Violin Plot - Age by Pclass', fontsize=13, fontweight='bold')
axes[0, 1].set_xlabel('Pclass', fontsize=11)
axes[0, 1].set_ylabel('Age', fontsize=11)
# 左下:箱ひげ図(性別別)
sns.boxplot(data=df, x='sex', y='fare', palette='Set2', ax=axes[1, 0])
axes[1, 0].set_title('Box Plot - Fare by Sex', fontsize=13, fontweight='bold')
axes[1, 0].set_xlabel('Sex', fontsize=11)
axes[1, 0].set_ylabel('Fare', fontsize=11)
axes[1, 0].set_ylim(0, 300)
# 右下:バイオリンプロット(性別別、生存状況で分割)
sns.violinplot(data=df, x='sex', y='fare', hue='survived',
split=True, palette='muted', ax=axes[1, 1])
axes[1, 1].set_title('Violin Plot - Fare by Sex and Survival', fontsize=13, fontweight='bold')
axes[1, 1].set_xlabel('Sex', fontsize=11)
axes[1, 1].set_ylabel('Fare', fontsize=11)
axes[1, 1].set_ylim(0, 300)
axes[1, 1].legend(title='Survived', labels=['No', 'Yes'])
plt.tight_layout()
plt.savefig('05_box_violin.png', dpi=150, bbox_inches='tight')
plt.show()
print("グラフを保存しました: 05_box_violin.png")
実行結果(クリックして展開)

バイオリンプロットは箱ひげ図に比べて、データの分布形状(単峰性、双峰性など)まで詳細に把握できます。1等客室は年齢層が広く、3等客室は比較的若い乗客が多いことがわかります。
3-2. 棒グラフで平均値と信頼区間(barplot)
各カテゴリの平均値を棒グラフで示し、黒い縦線で信頼区間(エラーバー) を表示します。
# 客室等級ごとの生存率(survivedの平均値)
plt.figure(figsize=(14, 6))
# 左側: 客室等級と性別による生存率
plt.subplot(1, 2, 1)
sns.barplot(
data=df,
x='pclass',
y='survived',
hue='sex',
errorbar='sd', # 標準偏差を表示
palette='rocket'
)
plt.title('Survival Rate by Pclass and Sex', fontsize=14, fontweight='bold')
plt.xlabel('Pclass', fontsize=12)
plt.ylabel('Survival Rate', fontsize=12)
plt.legend(title='Sex')
plt.ylim(0, 1)
# 右側: 乗船港による生存率
plt.subplot(1, 2, 2)
sns.barplot(
data=df.dropna(subset=['embarked']),
x='embarked',
y='survived',
hue='pclass',
errorbar='ci', # 95%信頼区間
palette='Set2'
)
plt.title('Survival Rate by Embarked Port and Pclass', fontsize=14, fontweight='bold')
plt.xlabel('Embarked', fontsize=12)
plt.ylabel('Survival Rate', fontsize=12)
plt.legend(title='Pclass')
plt.ylim(0, 1)
plt.tight_layout()
plt.savefig('06_barplot.png', dpi=150, bbox_inches='tight')
plt.show()
print("グラフを保存しました: 06_barplot.png")
実行結果(クリックして展開)

女性の生存率が男性より圧倒的に高く、特に1等客室の女性はほぼ全員が生存していることが明確です。乗船港別では、Cherbourg(C港)からの乗客の生存率が高い傾向があります。
実装レシピ4:高度な多変量解析を一行で
4-1. 全変数の散布図行列(pairplot)
複数の数値変数(特徴量)の組み合わせ全てについて、散布図と周辺分布(ヒストグラム) を一度に描画する究極のEDAツールです。
# 分析に使う数値列を抽出
cols = ['age', 'fare', 'sibsp', 'parch']
# pairplotを実行(hueでカテゴリ分けが可能)
g = sns.pairplot(
df.dropna(subset=cols),
vars=cols,
hue='survived',
diag_kind='kde', # 対角線に密度曲線を表示
plot_kws={'alpha': 0.6, 's': 30},
diag_kws={'alpha': 0.7},
palette='husl',
height=2.5
)
g.fig.suptitle('Pair Plot of Key Features by Survival',
y=1.02, fontsize=16, fontweight='bold')
plt.savefig('07_pairplot.png', dpi=150, bbox_inches='tight')
plt.show()
print("グラフを保存しました: 07_pairplot.png")
print(f"分析対象の特徴量: {cols}")
print(f"有効データ件数: {df.dropna(subset=cols).shape[0]}件")
実行結果(クリックして展開)

グラフを保存しました: 07_pairplot.png
分析対象の特徴量: ['age', 'fare', 'sibsp', 'parch']
有効データ件数: 712件
Pairplotにより、全ての変数の組み合わせを一度に確認できます。fare(運賃)が生存状況と関連が深いことが、複数の散布図から確認できます。
4-2. 相関のヒートマップ(heatmap)
全変数間の相関係数を色と数値で分かりやすく表示します。
# 相関行列を計算
numeric_cols = df.select_dtypes(include=np.number).columns.tolist()
corr_matrix = df[numeric_cols].corr().round(2)
# ヒートマップ描画
plt.figure(figsize=(12, 10))
mask = np.triu(np.ones_like(corr_matrix, dtype=bool), k=1) # 上三角を非表示
sns.heatmap(
corr_matrix,
mask=mask,
annot=True, # 数値を表示
fmt=".2f", # 小数点以下2桁
cmap='coolwarm', # 赤と青で正負を表現
center=0,
linewidths=1,
cbar_kws={"shrink": 0.8},
square=True
)
plt.title('Correlation Heatmap of Titanic Features',
fontsize=16, fontweight='bold', pad=20)
plt.xticks(rotation=45, ha='right')
plt.yticks(rotation=0)
plt.tight_layout()
plt.savefig('08_heatmap.png', dpi=150, bbox_inches='tight')
plt.show()
print("グラフを保存しました: 08_heatmap.png")
print(f"\n相関係数の高いペア(上位5組):")
# 相関係数の絶対値でソート
corr_pairs = corr_matrix.unstack().sort_values(ascending=False)
corr_pairs = corr_pairs[corr_pairs < 1] # 自己相関を除く
print(corr_pairs.head(5))
実行結果(クリックして展開)

グラフを保存しました: 08_heatmap.png
相関係数の高いペア(上位5組):
parch sibsp 0.41
fare survived 0.26
survived fare 0.26
parch fare 0.22
fare parch 0.22
dtype: float64
pclass(客室等級)とfare(運賃)の間に強い負の相関があり、等級が良いほど運賃が高いことが確認できます。survived(生存)との相関では、fareが正の相関を示しています。
【高度なテクニック】FacetGridとテーマ設定
Seabornの真の力は、FacetGrid を使ったグリッド化(多面展開) と、テーマ機能によるグラフの統一的なスタイル変更にあります。
1. FacetGridで条件別グラフを量産
# 'pclass'と'sex'の組み合わせでグラフをグリッド表示
g = sns.FacetGrid(
df,
col="pclass", # 列に客室等級
row="sex", # 行に性別
hue="survived", # 生存/死亡で色分け
height=3.5,
aspect=1.2,
margin_titles=True, # タイトルを外側に表示
palette='viridis'
)
# 描画したいグラフを指定(ここではヒストグラム)
g.map(sns.histplot, "age", kde=True, bins=15, alpha=0.7)
# 凡例を追加
g.add_legend(title="Survived")
g.fig.suptitle('Age Distribution by Pclass, Sex, and Survival',
y=1.02, fontsize=16, fontweight='bold')
plt.savefig('09_facetgrid.png', dpi=150, bbox_inches='tight')
plt.show()
print("グラフを保存しました: 09_facetgrid.png")
print("このグラフは6パターン(性別2 × 客室等級3)の年齢分布を一度に表示しています")
実行結果(クリックして展開)

グラフを保存しました: 09_facetgrid.png
このグラフは6パターン(性別2 × 客室等級3)の年齢分布を一度に表示しています
FacetGridにより、性別と客室等級の全組み合わせ(6パターン)の年齢分布を一度に比較できます。1等客室の女性は幅広い年齢層が生存しているのに対し、3等客室の男性は生存者が少ないことが一目瞭然です。
2. スタイル変更で一気にプロの仕上がり
# プロのデータ分析レポート風のスタイルに設定
sns.set_theme(style="whitegrid", context="talk")
# context="talk" はプレゼン資料向けに文字サイズを大きくする
# 例:scatter plotを描画
plt.figure(figsize=(12, 8))
sns.scatterplot(
data=df,
x='age',
y='fare',
size='parch', # 同乗した親/子供の数でサイズ変更
hue='sex', # 性別で色分け
style='survived', # 生存状況でマーカー形状を変更
sizes=(50, 400),
palette='tab10',
alpha=0.7
)
plt.title("Professional-Style Scatter Plot\n(Age vs Fare with Multiple Dimensions)",
fontsize=18, fontweight='bold', pad=20)
plt.xlabel('Age', fontsize=14)
plt.ylabel('Fare', fontsize=14)
plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left', fontsize=11)
plt.ylim(0, 300)
plt.tight_layout()
plt.savefig('10_professional_style.png', dpi=150, bbox_inches='tight')
plt.show()
# スタイルを元に戻す
sns.set_theme(style="whitegrid", context="notebook")
print("グラフを保存しました: 10_professional_style.png")
実行結果(クリックして展開)

一つのグラフに4つの次元(年齢、運賃、性別、生存状況)を表現し、さらに同乗した親/子供の数を点のサイズで表現しています。プレゼン資料向けの大きな文字サイズと洗練されたデザインで、聴衆に伝わりやすいグラフになります。
実践:タイタニックデータセットで検証してみた
検証タスク
「乗客の生存率に最も影響を与える要因」を高速に見つける。
実行コード(レシピの統合)
# 1. 前処理: 欠損値を含む行を除外(簡易化のため)
df_clean = df.dropna(subset=['age', 'pclass', 'sex', 'fare', 'survived'])
print(f"クリーニング後のデータ件数: {len(df_clean)}件")
print(f"除外されたデータ: {len(df) - len(df_clean)}件\n")
# 2. 多変量解析: 相関のヒートマップで全体を俯瞰(レシピ4-2)
print("=== 1. 相関の俯瞰(Heatmap)===")
# 性別を数値化(male=1, female=0)
df_clean['sex_numeric'] = df_clean['sex'].map({'male': 1, 'female': 0})
# 相関行列の計算
corr_cols = ['survived', 'pclass', 'sex_numeric', 'age', 'fare']
corr_matrix = df_clean[corr_cols].corr().round(2)
plt.figure(figsize=(8, 6))
sns.heatmap(corr_matrix, annot=True, cmap='RdYlBu_r', center=0,
linewidths=2, square=True, cbar_kws={"shrink": 0.8})
plt.title('Correlation Matrix (Cleaned Data)', fontsize=14, fontweight='bold')
plt.tight_layout()
plt.savefig('11_analysis_correlation.png', dpi=150, bbox_inches='tight')
plt.show()
# 生存率との相関を表示
print("\n生存率との相関係数:")
print(corr_matrix['survived'].sort_values(ascending=False))
# 3. 関係性の深掘り: カテゴリ別の生存率(Barplot、レシピ3-2)
print("\n=== 2. 性別・客室等級と生存率の関係(Barplot)===")
plt.figure(figsize=(12, 5))
# 左側: 性別と客室等級による生存率
plt.subplot(1, 2, 1)
sns.barplot(
data=df_clean,
x='pclass',
y='survived',
hue='sex',
palette='deep',
errorbar='ci'
)
plt.title('Survival Rate by Pclass and Sex', fontsize=14, fontweight='bold')
plt.xlabel('Pclass', fontsize=12)
plt.ylabel('Survival Rate', fontsize=12)
plt.legend(title='Sex')
plt.ylim(0, 1)
# 右側: カテゴリ別の生存者数
plt.subplot(1, 2, 2)
survival_counts = df_clean.groupby(['sex', 'pclass', 'survived']).size().unstack(fill_value=0)
survival_counts.plot(kind='bar', stacked=True, ax=plt.gca(), color=['#d62728', '#2ca02c'])
plt.title('Survival Count by Sex and Pclass', fontsize=14, fontweight='bold')
plt.xlabel('(Sex, Pclass)', fontsize=12)
plt.ylabel('Count', fontsize=12)
plt.legend(title='Survived', labels=['No', 'Yes'])
plt.xticks(rotation=45, ha='right')
plt.tight_layout()
plt.savefig('11_analysis_survival.png', dpi=150, bbox_inches='tight')
plt.show()
# 詳細な統計
print("\n性別・客室等級別の生存率:")
survival_rate = df_clean.groupby(['sex', 'pclass'])['survived'].agg(['mean', 'count'])
survival_rate.columns = ['Survival Rate', 'Count']
survival_rate['Survival Rate'] = (survival_rate['Survival Rate'] * 100).round(1)
print(survival_rate)
実行結果(クリックして展開)
クリーニング後のデータ件数: 712件
除外されたデータ: 179件
=== 1. 相関の俯瞰(Heatmap)===
生存率との相関係数:
survived 1.00
fare 0.26
age -0.08
pclass -0.34
sex_numeric -0.54
Name: survived, dtype: float64
=== 2. 性別・客室等級と生存率の関係(Barplot)===
性別・客室等級別の生存率:
Survival Rate Count
sex pclass
female 1 96.8 85
2 88.0 74
3 49.0 102
male 1 34.5 87
2 14.5 110
3 13.5 244


検証結果の考察
1. 相関行列(Heatmap)の洞察
-
survivedとの相関が最も高いのは、sex_numeric(-0.54)とpclass(-0.34) - 特に
sex_numericは負の相関で、女性(0)の方が生存率が高いことを示す -
fare(運賃)も正の相関(0.26)があり、高額な運賃を支払った乗客ほど生存率が高い傾向
2. カテゴリ別生存率(Barplot)の洞察
-
女性はどの客室等級でも男性より圧倒的に生存率が高い
- 1等客室の女性: 96.8%(ほぼ全員が生存)
- 2等客室の女性: 88.0%
- 3等客室の女性: 49.0%
-
男性の生存率は全体的に低い
- 1等客室の男性: 34.5%
- 2等客室の男性: 14.5%
- 3等客室の男性: 13.5%(最も低い)
3. 結論
Seabornの高速レシピにより、「性別が最も強い要因で、次に客室等級が影響する」というタイタニックデータの核心的な洞察を、わずか数行、数秒で得ることができました。
この結果は「女性と子供を優先」という当時の避難方針を反映しており、歴史的事実とも一致します。
まとめ
今回学んだこと
- 📈 SeabornがMatplotlibよりも高速なEDAに適している理由
- 📊
histplot,kdeplot,regplotによる単変量・二変量解析の基本レシピ - 🚀
jointplot,pairplot,heatmapによる高度な多変量解析の一行実装 - 🎨
FacetGridとset_themeによるグラフの表現力向上 - 🔍 実データ(タイタニック)での検証により、データから洞察を引き出すプロセスを体験
使い分けの指針
| 分析タスク | 推奨Seaborn関数 | 理由 |
|---|---|---|
| 全変数の関係を一目で把握 | pairplot |
全ての組み合わせを一度に描画 |
| 二変数の相関と分布を同時に確認 | jointplot |
散布図と周辺ヒストグラムを統合 |
| カテゴリ別の分布の形を比較 | violinplot |
分布の密度まで詳細に比較可能 |
| 統計的な平均値の差を検証 | barplot |
信頼区間(エラーバー)で統計的な判断を補助 |
| 複数条件での比較を一度に | FacetGrid |
グリッド表示で条件別のパターンを把握 |
| 変数間の相関を俯瞰 | heatmap |
全変数の相関係数を色と数値で可視化 |
次のステップ
-
⚙️ 特徴量エンジニアリング: グラフから得た洞察(例:
ageやfareの偏り)を元に、新しい特徴量を作成する# 例:年齢層のカテゴリ化 df['age_group'] = pd.cut(df['age'], bins=[0, 12, 18, 60, 100], labels=['child', 'teen', 'adult', 'senior']) # 例:家族の人数 df['family_size'] = df['sibsp'] + df['parch'] + 1 -
🤖 機械学習モデルへ: 探索を終えたクリーンなデータセットで、分類モデル(決定木、ランダムフォレストなど)を構築し、予測精度を検証する
-
📝 レポート自動化: 複数のグラフを自動生成し、分析レポートを簡単に作成するパイプラインを構築する
# 例:レポート生成の自動化 import os # 出力ディレクトリの作成 os.makedirs('output', exist_ok=True) # すべてのグラフを一括生成 graphs = [ ('histplot', lambda: create_histplot()), ('kdeplot', lambda: create_kdeplot()), # ... 他のグラフ関数 ] for name, func in graphs: func() plt.savefig(f'output/{name}.png', dpi=150, bbox_inches='tight') plt.close()
コード全体のまとめ
すべてのコードを順番に実行する場合は、以下のようにまとめて実行できます:
# ===== 完全な実行コード =====
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import warnings
warnings.filterwarnings('ignore')
plt.rcParams['figure.figsize'] = (10, 6)
plt.rcParams['figure.dpi'] = 100
sns.set_style("whitegrid")
# データ読み込み
df = sns.load_dataset('titanic')
print(f"データ読み込み完了: {len(df)}行 × {len(df.columns)}列")
# 出力ディレクトリの作成
import os
os.makedirs('seaborn_output', exist_ok=True)
# ここから各レシピのコードを順次実行
# (上記の各セクションのコードをコピー&ペースト)
print("\n全てのグラフが seaborn_output/ に保存されました!")
最後に
最後まで読んでくださり、ありがとうございました!
今回のレシピが、皆さんのデータサイエンスの学習と実務の効率化に繋がれば幸いです。
データの可視化は、単なるグラフの描画ではなく、データとの対話そのものです。Seabornを使いこなせば、その対話をより深く、より高速に行うことができます。
実際にコードを実行し、グラフを眺めながら「なぜこのような分布になるのか?」「このパターンから何が読み取れるか?」と考えることで、データサイエンスのスキルは飛躍的に向上します。
生成AI、データ分析、深層学習を体系的に学び、プロの指導のもとで実践的なAIスキルを習得したい方、キャリアの幅を広げたい方や副業を目指す方は、ぜひこちらからお問い合わせください。
Discussion