1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Pythonでデータ可視化 — matplotlibとseabornを最低限使えるようにした

1
Posted at

はじめに

データ処理ができるようになってきたので、次は可視化。

PHPではグラフ描画はフロントエンドに丸投げしていた。Chart.jsのデータをAPIで返すか、Excelに貼ってもらうかのどちらかで、サーバーサイドでグラフを生成することはほぼなかった。Pythonはサーバーサイドでグラフを作ってファイル保存できるので発想自体が違った。

ライブラリは2つ使う。matplotlibが基盤で、seabornはそれを使いやすくしたラッパー。最初はseabornだけ使えればいいかと思っていたが、細かい調整はmatplotlibを触る必要があるので両方覚えた。


インストール

pip install matplotlib seaborn
import matplotlib.pyplot as plt
import matplotlib         as mpl
import seaborn            as sns
import pandas             as pd
import numpy              as np

日本語フォントの設定

デフォルトだと日本語が文字化けする。これを最初に設定しておく。

# Mac
plt.rcParams["font.family"] = "Hiragino Sans"

# Windows
plt.rcParams["font.family"] = "MS Gothic"

# 環境を選ばない方法(japanize-matplotlibを使う)
# pip install japanize-matplotlib
import japanize_matplotlib  # importするだけで日本語が使えるようになる

日本語フォントの設定は最初にハマるポイントなので先に解決しておく。


matplotlib基本 — グラフの構造を理解する

matplotlibにはFigureAxesという概念がある。

Figure(キャンバス全体)
└── Axes(グラフ1つ分)
    ├── x軸
    ├── y軸
    ├── タイトル
    └── プロット内容
# シンプルな書き方(小さいグラフ1つのとき)
plt.plot([1, 2, 3, 4], [10, 20, 15, 30])
plt.title("シンプルな折れ線グラフ")
plt.xlabel("x軸")
plt.ylabel("y軸")
plt.savefig("graph.png", dpi=150, bbox_inches="tight")
plt.show()
plt.close()
# オブジェクト指向スタイル(推奨)
fig, ax = plt.subplots(figsize=(8, 5))

ax.plot([1, 2, 3, 4], [10, 20, 15, 30])
ax.set_title("折れ線グラフ")
ax.set_xlabel("x軸")
ax.set_ylabel("y軸")

plt.tight_layout()
plt.savefig("graph.png", dpi=150, bbox_inches="tight")
plt.show()
plt.close()

後者のオブジェクト指向スタイルが推奨されている。最初に書き方を統一しておかないと混乱する。


折れ線グラフ

時系列データの可視化でよく使う。

import pandas as pd
import matplotlib.pyplot as plt
import japanize_matplotlib

# サンプルデータ
monthly_sales = pd.DataFrame({
    "month":  [1, 2, 3, 4, 5, 6],
    "東京":   [120, 135, 148, 162, 155, 178],
    "大阪":   [98,  105, 112, 108, 120, 115],
    "福岡":   [45,  52,  48,  55,  61,  58 ],
})

fig, ax = plt.subplots(figsize=(10, 6))

for region in ["東京", "大阪", "福岡"]:
    ax.plot(
        monthly_sales["month"],
        monthly_sales[region],
        marker="o",    # データ点にマーカーをつける
        label=region,
        linewidth=2,
    )

ax.set_title("月次売上推移(地域別)")
ax.set_xlabel("")
ax.set_ylabel("売上(万円)")
ax.legend()                         # 凡例
ax.grid(True, alpha=0.3)            # グリッド線(薄め)
ax.set_xticks(monthly_sales["month"])  # x軸の目盛りを整数に

plt.tight_layout()
plt.savefig("line_chart.png", dpi=150, bbox_inches="tight")
plt.close()

棒グラフ

カテゴリ別の比較でよく使う。

categories = ["食品", "日用品", "電化製品", "衣類", "その他"]
values     = [320, 185, 240, 155, 98]

fig, ax = plt.subplots(figsize=(9, 5))

bars = ax.bar(
    categories,
    values,
    color=["#4C72B0", "#DD8452", "#55A868", "#C44E52", "#8172B3"],
    edgecolor="white",
    linewidth=0.5,
)

# 棒の上に数値を表示
for bar, val in zip(bars, values):
    ax.text(
        bar.get_x() + bar.get_width() / 2,
        bar.get_height() + 5,
        f"{val}",
        ha="center",
        va="bottom",
        fontsize=11,
    )

ax.set_title("カテゴリ別売上")
ax.set_ylabel("売上(万円)")
ax.set_ylim(0, max(values) * 1.15)  # y軸の上限に余白
ax.grid(axis="y", alpha=0.3)
ax.spines["top"].set_visible(False)    # 上の枠線を消す
ax.spines["right"].set_visible(False)  # 右の枠線を消す

plt.tight_layout()
plt.savefig("bar_chart.png", dpi=150, bbox_inches="tight")
plt.close()

散布図

2変数の相関を見るときに使う。

np.random.seed(42)
n = 100

df = pd.DataFrame({
    "広告費": np.random.uniform(50, 500, n),
    "売上":   np.random.uniform(100, 1000, n),
    "地域":   np.random.choice(["東京", "大阪", "福岡"], n),
})
df["売上"] = df["広告費"] * 1.8 + np.random.normal(0, 80, n)

fig, ax = plt.subplots(figsize=(8, 6))

# 地域ごとに色分けして散布
colors = {"東京": "#4C72B0", "大阪": "#DD8452", "福岡": "#55A868"}
for region, group in df.groupby("地域"):
    ax.scatter(
        group["広告費"],
        group["売上"],
        c=colors[region],
        label=region,
        alpha=0.6,
        s=60,
    )

ax.set_title("広告費と売上の関係")
ax.set_xlabel("広告費(万円)")
ax.set_ylabel("売上(万円)")
ax.legend()
ax.grid(True, alpha=0.3)

plt.tight_layout()
plt.savefig("scatter.png", dpi=150, bbox_inches="tight")
plt.close()

seaborn — matplotlibをラップした高レベルAPI

seabornを使うとより少ないコードで見栄えのいいグラフが書ける。

import seaborn as sns

# テーマ設定(whitegrid が見やすい)
sns.set_theme(style="whitegrid", palette="muted")

seabornの棒グラフ

fig, ax = plt.subplots(figsize=(9, 5))

sns.barplot(
    data=df,
    x="category",
    y="amount",
    hue="region",   # グループ分け
    ax=ax,
)

ax.set_title("カテゴリ×地域別売上")
ax.set_xlabel("カテゴリ")
ax.set_ylabel("売上")
ax.legend(title="地域")

plt.tight_layout()
plt.savefig("seaborn_bar.png", dpi=150, bbox_inches="tight")
plt.close()

ヒストグラム + KDE(分布の確認)

fig, ax = plt.subplots(figsize=(8, 5))

sns.histplot(
    data=df,
    x="amount",
    bins=30,
    kde=True,   # 密度曲線も一緒に描く
    ax=ax,
)

ax.set_title("金額の分布")
ax.set_xlabel("金額")
ax.set_ylabel("件数")

plt.tight_layout()
plt.savefig("histogram.png", dpi=150, bbox_inches="tight")
plt.close()

ヒートマップ — 相関行列の可視化

pandasの集計結果と組み合わせて使うことが多い。

# 相関行列を計算
corr_matrix = df[["広告費", "売上", "客数", "単価"]].corr()

fig, ax = plt.subplots(figsize=(7, 6))

sns.heatmap(
    corr_matrix,
    annot=True,    # セルに数値を表示
    fmt=".2f",     # 小数点2桁
    cmap="coolwarm",
    vmin=-1,
    vmax=1,
    ax=ax,
)

ax.set_title("相関行列")

plt.tight_layout()
plt.savefig("heatmap.png", dpi=150, bbox_inches="tight")
plt.close()

boxplot — 分布の比較

fig, ax = plt.subplots(figsize=(8, 5))

sns.boxplot(
    data=df,
    x="region",
    y="amount",
    palette="muted",
    ax=ax,
)

ax.set_title("地域別の金額分布")
ax.set_xlabel("地域")
ax.set_ylabel("金額")

plt.tight_layout()
plt.savefig("boxplot.png", dpi=150, bbox_inches="tight")
plt.close()

複数グラフを並べる

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

# 左のグラフ
axes[0].bar(categories, values, color="#4C72B0")
axes[0].set_title("カテゴリ別売上")
axes[0].set_ylabel("売上(万円)")
axes[0].grid(axis="y", alpha=0.3)

# 右のグラフ
axes[1].plot(months, trends, marker="o", color="#DD8452")
axes[1].set_title("月次推移")
axes[1].set_xlabel("")
axes[1].set_ylabel("売上(万円)")
axes[1].grid(True, alpha=0.3)

plt.suptitle("売上サマリー", fontsize=14, y=1.02)
plt.tight_layout()
plt.savefig("summary.png", dpi=150, bbox_inches="tight")
plt.close()

subplots(行数, 列数)で複数のAxesを作れる。レポート用に複数グラフを1ファイルにまとめるときに使う。


グラフをファイルに保存する

# PNG(ラスタ形式)
plt.savefig("graph.png", dpi=150, bbox_inches="tight")

# SVG(ベクタ形式 — 拡大しても綺麗)
plt.savefig("graph.svg", bbox_inches="tight")

# PDF
plt.savefig("graph.pdf", bbox_inches="tight")

bbox_inches="tight"を忘れるとタイトルや軸ラベルが切れることがある。毎回つけるのが無難。

dpi=150は解像度。印刷用なら300、Web表示なら72〜150が目安。


matplotlibとseabornの使い分け

用途 推奨
折れ線グラフ matplotlib
シンプルな棒グラフ matplotlib
グループ別棒グラフ seaborn
散布図(色分けなし) matplotlib
散布図(色分けあり) seaborn
ヒストグラム seaborn
ヒートマップ seaborn
boxplot seaborn
細かいカスタマイズ matplotlib

seabornはDataFrameを直接渡せてhueでグループ分けが簡単なので、グループ比較の可視化に向いている。細かい見た目の調整はmatplotlibのAPIを直接触る必要がある。


まとめ

  • matplotlibが基盤、seabornはそのラッパー
  • Figureがキャンバス、Axesが個々のグラフ
  • オブジェクト指向スタイル(fig, ax = plt.subplots())で統一する
  • 日本語はjapanize_matplotlibを入れておくと楽
  • savefig()にはbbox_inches="tight"を常につける

PHPでフロントに任せていたグラフ描画をサーバーサイドで完結できるようになった。レポート生成バッチなどで使う場面が出てきそうなので引き続き慣れていきたい。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?