Machine Learning: Matplotlib & Seabornによる可視化

最終更新:2026-08-26

優れたグラフは千行のデータに匹敵する — 可視化はパターン発見の第一歩です。

1. 学習内容


2. プロダクトマネージャーの実体験

(1) 課題:表データではトレンドと異常が見えない

BobはSalesPredictの月次売上レポートをチームに共有しました。50行のExcelデータを見ても、どのカテゴリが下落しているのか、どの月に異常な変動があったのかを素早く把握できる人はいませんでした。Aliceの米国データのトレンドは中国データとまったく異なりますが、生の数字を眺めているだけではその違いに気づくことはほぼ不可能です。データはスプレッドシートに埋もれ、重要なインサイトはかき消されていました。

(2) 可視化による解決策

たった1つの折れ線グラフで、第3四半期のElectronicsカテゴリの明確な下降トレンドが即座に判明しました。ヒートマップでは、広告費と売上の相関が予想を大きく上回っていることがわかりました。

PYTHON
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd

# Quick visualization reveals hidden patterns
df = pd.read_csv("monthly_sales.csv")
fig, axes = plt.subplots(1, 2, figsize=(14, 5))
df.plot(x="month", y="revenue", ax=axes[0], title="Revenue Trend")
sns.heatmap(df.corr(numeric_only=True), annot=True, ax=axes[1])
plt.tight_layout()
plt.savefig("sales_overview.png", dpi=150)

(3) 成果:5分で重要なビジネスインサイトを発見

生のテーブルを可視化に置き換えた結果、Bobは5分以内に第3四半期のElectronicsカテゴリの15%減少を発見しました。タイムリーに広告戦略を調整し、約20万ドルの損失を回避できました。


3. Matplotlibの基礎

(1) Figure/Axesシステム

Matplotlibは2層アーキテクチャを採用しています。Figure(キャンバス)が1つ以上のAxes(描画領域)を含みます。

100%
graph TB
    FIG[Figure - Canvas] --> AX1[Axes 1<br/>Subplot 1]
    FIG --> AX2[Axes 2<br/>Subplot 2]
    AX1 --> LINE[Line Chart]
    AX2 --> BAR[Bar Chart]

▶ サンプル:基本的な折れ線グラフの作成

PYTHON
import matplotlib.pyplot as plt

# Monthly revenue data (thousand USD)
months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun",
          "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
revenue = [120, 135, 150, 142, 160, 175, 180, 190, 195, 200, 220, 250]

fig, ax = plt.subplots(figsize=(10, 5))
ax.plot(months, revenue, marker="o", linewidth=2, color="#2196F3")
ax.set_title("Monthly Revenue Trend", fontsize=14)
ax.set_xlabel("Month")
ax.set_ylabel("Revenue (thousand USD)")
ax.grid(True, alpha=0.3)
ax.fill_between(months, revenue, alpha=0.1, color="#2196F3")

# Annotate peak
peak_idx = revenue.index(max(revenue))
ax.annotate(f"Peak: {max(revenue)}k", xy=(peak_idx, max(revenue)),
            xytext=(peak_idx-2, max(revenue)+15),
            arrowprops=dict(arrowstyle="->", color="red"))

plt.tight_layout()
plt.savefig("revenue_trend.png", dpi=150)

出力:

TEXT 📖 参照専用
# Executed successfully

(2) よく使われるグラフの種類

▶ サンプル:棒グラフと散布図

PYTHON
import matplotlib.pyplot as plt
import numpy as np

fig, axes = plt.subplots(1, 2, figsize=(14, 5))

# Bar chart: category revenue
categories = ["Electronics", "Clothing", "Food", "Books", "Home"]
revenue = [2500, 1450, 900, 700, 4000]
colors = ["#FF6384", "#36A2EB", "#FFCE56", "#4BC0C0", "#9966FF"]

axes[0].barh(categories, revenue, color=colors)
axes[0].set_title("Revenue by Category")
axes[0].set_xlabel("Revenue (thousand USD)")

# Scatter plot: ad spend vs revenue
np.random.seed(42)
ad_spend = np.random.uniform(10, 100, 50)
sales = 50 + 0.8 * ad_spend + np.random.normal(0, 10, 50)

axes[1].scatter(ad_spend, sales, alpha=0.6, color="#2196F3", edgecolors="white")
axes[1].set_title("Ad Spend vs Revenue")
axes[1].set_xlabel("Ad Spend (thousand USD)")
axes[1].set_ylabel("Revenue (thousand USD)")

# Add trend line
z = np.polyfit(ad_spend, sales, 1)
p = np.poly1d(z)
axes[1].plot(ad_spend, p(ad_spend), "r--", alpha=0.8, linewidth=2)

plt.tight_layout()
plt.savefig("bar_scatter.png", dpi=150)

出力:

TEXT 📖 参照専用
# Executed successfully
グラフの種類 最適な用途 Matplotlibの関数
折れ線グラフ 時系列トレンド ax.plot()
棒グラフ カテゴリ比較 ax.bar() / ax.barh()
散布図 2変数の関係性 ax.scatter()
円グラフ 構成比の分布 ax.pie()
ヒストグラム 1変数の分布 ax.hist()

4. Seabornの高度なグラフ

SeabornはMatplotlibの上に構築されており、より高レベルな統計グラフと洗練されたデフォルトスタイルを提供します。

(1) 分布プロット

▶ サンプル:注文金額の分布分析

PYTHON
import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np

# Generate order amount data
rng = np.random.default_rng(42)
orders_normal = rng.normal(150, 50, 1000)
orders_normal = orders_normal[orders_normal > 0]  # Remove negatives

fig, axes = plt.subplots(1, 2, figsize=(14, 5))

# Histogram with KDE
sns.histplot(orders_normal, bins=30, kde=True, ax=axes[0], color="#2196F3")
axes[0].set_title("Order Amount Distribution")
axes[0].set_xlabel("Amount (USD)")

# Box plot by category
categories = rng.choice(["Electronics", "Clothing", "Food"], 500)
amounts = np.where(categories == "Electronics",
                   rng.normal(300, 80, 500),
                   np.where(categories == "Clothing",
                            rng.normal(120, 40, 500),
                            rng.normal(50, 20, 500)))
amounts = np.clip(amounts, 1, None)
data = {"category": categories, "amount": amounts}

sns.boxplot(data=data, x="category", y="amount", ax=axes[1], palette="Set2")
axes[1].set_title("Order Amount by Category")

plt.tight_layout()
plt.savefig("distribution.png", dpi=150)

出力:

TEXT 📖 参照専用
# Executed successfully

(2) ヒートマップ

▶ サンプル:特徴量の相関ヒートマップ

PYTHON
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

# Simulate SalesPredict feature correlations
np.random.seed(42)
n = 200
ad_spend = np.random.uniform(10, 100, n)
traffic = ad_spend * 1.2 + np.random.normal(0, 15, n)
conversion = traffic * 0.03 + np.random.normal(0, 0.5, n)
revenue = conversion * 150 + np.random.normal(0, 500, n)
customer_age = np.random.uniform(18, 65, n)

df = pd.DataFrame({
    "ad_spend": ad_spend,
    "traffic": traffic,
    "conversion_rate": conversion,
    "revenue": revenue,
    "customer_age": customer_age,
})

corr = df.corr()

fig, ax = plt.subplots(figsize=(8, 6))
sns.heatmap(corr, annot=True, fmt=".2f", cmap="RdBu_r",
            center=0, vmin=-1, vmax=1, ax=ax,
            square=True, linewidths=0.5)
ax.set_title("Feature Correlation Heatmap")
plt.tight_layout()
plt.savefig("correlation_heatmap.png", dpi=150)

出力:

TEXT 📖 参照専用
# Executed successfully

(3) 複数サブプロットのレイアウト

▶ サンプル:SalesPredictの4次元分析パネル

PYTHON
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

rng = np.random.default_rng(42)
df = pd.DataFrame({
    "date": pd.date_range("2024-01-01", periods=90),
    "revenue": rng.normal(5000, 1000, 90).cumsum(),
    "category": rng.choice(["Elec", "Cloth", "Food"], 90),
    "orders": rng.integers(50, 200, 90),
})

fig, axes = plt.subplots(2, 2, figsize=(14, 10))

# (1) Revenue trend
axes[0, 0].plot(df["date"], df["revenue"], color="#2196F3")
axes[0, 0].set_title("Daily Revenue Trend")

# (2) Category distribution
cat_rev = df.groupby("category")["revenue"].sum()
axes[0, 1].pie(cat_rev, labels=cat_rev.index, autopct="%1.1f%%")

# (3) Orders distribution
sns.histplot(df["orders"], bins=20, kde=True, ax=axes[1, 0], color="#4CAF50")
axes[1, 0].set_title("Orders Distribution")

# (4) Revenue vs Orders
axes[1, 1].scatter(df["orders"], df["revenue"], alpha=0.5, c="#FF5722")
axes[1, 1].set_title("Revenue vs Orders")

plt.tight_layout()
plt.savefig("dashboard.png", dpi=150)

出力:

TEXT 📖 参照専用
# Executed successfully

5. スタイルカスタマイズとグラフの選択

(1) Seabornのテーマとカラーパレット

PYTHON
import seaborn as sns

# Set global theme
sns.set_theme(style="whitegrid", palette="muted", font_scale=1.2)

# Available themes: darkgrid, whitegrid, dark, white, ticks
# Available palettes: deep, muted, pastel, bright, dark, colorblind
テーマ 背景 グリッド 最適な用途
darkgrid ダーク あり データの密集した表示
whitegrid ホワイト あり 学術レポート
dark ダーク なし プレゼンテーション
white ホワイト なし 論文
ticks ホワイト なし ミニマルスタイル

(2) グラフ選択の判断ガイド

100%
graph TB
    DATA[Data Type] --> CAT[Categorical]
    DATA --> NUM[Numerical]
    DATA --> TIME[Time Series]
    CAT --> COMP[Comparison<br/>Bar Chart]
    CAT --> PART[Part of Whole<br/>Pie / Stacked Bar]
    NUM --> DIST[Distribution<br/>Histogram / KDE / Box]
    NUM --> REL[Relationship<br/>Scatter / Heatmap]
    TIME --> TREND[Trend<br/>Line Chart]
    TIME --> SEA[Seasonality<br/>Seasonal Plot]

▶ サンプル:CJKフォントの設定

PYTHON
import matplotlib.pyplot as plt

# Method 1: Use SimHei font (Windows)
plt.rcParams["font.sans-serif"] = ["SimHei", "Microsoft YaHei"]
plt.rcParams["axes.unicode_minus"] = False

# Method 2: Use English labels (recommended for i18n)
# Keep all labels in English to avoid font issues across platforms
fig, ax = plt.subplots()
ax.set_title("Monthly Sales Report")  # English for compatibility
ax.set_xlabel("Month")
ax.set_ylabel("Revenue (thousand USD)")

出力:

TEXT 📖 参照専用
# Executed successfully

❓ よくある質問

Q MatplotlibとSeabornのどちらを使うべきですか?
A 日常的な分析にはSeaborn(よりクリーンで洗練されている)、細かな制御が必要な場合はMatplotlibを使ってください。SeabornはMatplotlibの上に構築されているため、自由に組み合わせて使えます。
Q グラフ内のCJK文字が文字化けする場合はどうすればいいですか?
A plt.rcParams["font.sans-serif"] にCJKフォントを設定してください。ただし、クロスプラットフォームのフォント問題を避けるため、英語ラベルの使用を推奨します。
Q 保存した画像がぼやけます。どうすればいいですか?
A dpiパラメータを設定してください:plt.savefig("fig.png", dpi=150)。論文には300以上、Webには100〜150が目安です。ベクターグラフィックが必要な場合は .svg または .pdf 形式を使用してください。
Q 適切なグラフの種類はどう選べばいいですか?
A データの種類と目的によります。時系列トレンドには折れ線グラフ、カテゴリ比較には棒グラフ、分布にはヒストグラム・箱ひげ図、2変数の関係性には散布図・ヒートマップを使用します。
Q Seabornの hue パラメータは何をするものですか?
A hue は指定した列でデータをグループ化し、色分けします。例えば、sns.scatterplot(data=df, x="ad_spend", y="revenue", hue="category") はカテゴリごとに異なる色を割り当てます。
Q サブプロットの間隔が狭すぎる場合はどうすればいいですか?
A plt.tight_layout() で自動調整するか、plt.subplots_adjust(hspace=0.3, wspace=0.3) で手動で間隔を制御してください。

📖 まとめ


📝 練習問題

  1. 基礎(難易度 ⭐):Matplotlibを使って12ヶ月間の売上トレンドを示す折れ線グラフを描画してください。タイトルと軸ラベルを追加しましょう。ヒント:セクション3の折れ線グラフの例を参照してください。
  2. 中級(難易度 ⭐⭐):Seabornを使って2x2のサブプロットパネルを作成してください。折れ線グラフ(トレンド)、棒グラフ(カテゴリ比較)、箱ひげ図(分布)、ヒートマップ(相関)を、シミュレートしたSalesPredictデータで描画します。ヒント:plt.subplots(2,2) + sns.xxx(ax=axes[i,j])
  3. チャレンジ(難易度 ⭐⭐⭐):インタラクティブダッシュボードのコンセプトを作成してください。月次売上トレンドのグラフを描き、「プロモーション月」と「通常月」を異なる色でハイライトし、プロモーション効果を説明する注釈を追加してください。ヒント:ax.axvspan() で領域を塗りつぶし、ax.annotate() で注釈を追加します。

← 前へ: Pandasデータ処理 | 次へ: Scikit-learn入門 →

Web-Tutorial.com

Web-Tutorial 技術チーム

複数の開発者によって共同維持されているプログラミングチュートリアルプラットフォーム。各チュートリアルは専門分野の開発者が執筆・レビューしています。正確で信頼性の高いコンテンツを目指しています — 問題を見つけた場合はお知らせください。

100%