コンテンツにスキップ

第02回: グラフ種類の選択

資料のダウンロード

ファイル 内容
exercise.py ハンズオン演習スクリプト

ヒントの使い方

python exercise.py --hint 1            # 方向性ヒント
python exercise.py --hint 1 --level 2  # より具体的なヒント
python exercise.py --hint 1 --level 3  # コード例
python exercise.py --check             # 提出前の自己チェック

演習問題への取り組み方

  1. 下の講義ノートを読む(事前学習・2時間目安)
  2. exercise.py を実行してグラフを確認する
  3. 演習問題(5問)に取り組む
  4. python exercise.py --check で確認する
  5. exercise.py を提出する(締切は授業後1週間)

詰まったとき

# ヒントを見る
python exercise.py --hint N --level 1

# AIに質問する
python ../../ask.py "質問内容"

解決しない場合は Q&A ページの投稿フォームを使ってください。


講義ノート

授業目標

  1. データの種類・問い・比較対象の数に基づいて適切なグラフ種類を選べる。
  2. 6種類の基本グラフ(棒グラフ・折れ線グラフ・散布図・ヒストグラム・箱ひげ図・ヒートマップ)を matplotlib / seaborn で実装できる。
  3. 不適切なグラフ選択が引き起こす誤読のパターンを説明できる。

グラフ選択チートシート

見せたいこと データの型 推奨グラフ 避けるべき例
カテゴリ間の比較 質的×量的 棒グラフ / 水平棒グラフ 折れ線グラフ(連続性を示唆するため不適)
時系列の推移 時間×量的 折れ線グラフ 棒グラフ(変化率が読みにくい)
2変数の相関 量的×量的 散布図 棒グラフ(集計してしまうと関係が消える)
1変数の分布 量的 ヒストグラム / KDE 棒グラフ(ビンを手動設定しないと誤読)
グループ別の分布比較 質的×量的 箱ひげ図 / バイオリン図 棒グラフ平均のみ(ばらつきが消える)
多変数の関係一覧 量的×量的 (多変数) ヒートマップ(相関行列) 多重折れ線(線が重なって読めない)
割合の比較 質的×割合 積み上げ棒グラフ / ドット図 円グラフ(角度の比較は不正確)

各グラフの適用場面と注意点

1. 棒グラフ (Bar Chart)

適用場面: カテゴリ変数に対する量的変数の集計値(平均・合計・件数)を比較する。

実装のポイント:

ax.bar(summary["place_type"], summary["happiness_score"], color=colors, width=0.6)
ax.set_ylim(0, 10)  # 必ず 0 始まり

注意点: - Y軸は必ず 0 始まりにする(第01回の Lie Factor 参照)。 - カテゴリが多い(8個超)場合は水平棒グラフ barh() に切り替えるとラベルが読みやすい。 - 棒の上に数値を表示する ax.text() を加えると、読み取り精度が向上する。 - エラーバー (yerr=) を追加して不確かさを示すと誠実なグラフになる。

よくある誤用: カテゴリに順序がないのに折れ線グラフを使う。折れ線グラフは「連続した変化」を暗示するため、「公園→駅前→商業施設」のような名義カテゴリには不適切。


2. 折れ線グラフ (Line Chart)

適用場面: 時間軸や連続値に沿った変化・トレンドを表現する。

実装のポイント:

ax.plot(sub["week"], sub["happiness_score"],
        label=pt, linewidth=1.5, marker="o", markersize=3)

注意点: - X軸が時間・順序のある変数のときのみ使用する。 - 系列数(line)が増えると視覚的に混雑する。5系列が上限の目安。6系列以上なら FacetGrid で分割するか、ハイライトしたい系列以外をグレーにするなど工夫する。 - marker を付けると個々のデータ点が明確になる。週次データなど点数が少ない場合は有効。 - Y軸を途中から始めることは折れ線グラフでは状況により許容されるが、その場合は必ず軸のスケールを明示する。


3. 散布図 (Scatter Plot)

適用場面: 2つの量的変数の相関・分布・外れ値・クラスタを探索する。

実装のポイント:

ax.scatter(sub["noise_level"], sub["happiness_score"],
           color=color, alpha=0.5, s=20, edgecolors="none")

# 回帰直線を重ねる
coef = np.polyfit(x, y, 1)
ax.plot(x_line, np.polyval(coef, x_line), linestyle="--")

注意点: - データ点数が多い場合は alpha を小さく(0.1〜0.3)してオーバープロット(重なり)を軽減する。さらに多い場合は2次元ヒストグラム (hist2d) やヘキサビン図 (hexbin) を検討する。 - 回帰直線を重ねると傾向が一目でわかるが、相関 ≠ 因果であることを必ず注意書きする。 - place_type などのカテゴリ変数で色分けすると、グループ間の差異も同時に見える。


4. ヒストグラム (Histogram)

適用場面: 1つの量的変数の度数分布(形状・偏り・多峰性)を確認する。

実装のポイント:

ax.hist(df["happiness_score"], bins=30, density=True, alpha=0.8)

from scipy.stats import gaussian_kde
kde = gaussian_kde(df["happiness_score"])
ax.plot(x_kde, kde(x_kde), linewidth=2)  # KDE を重ねる

注意点: - ビン幅の選択がグラフの印象を大きく左右する。bins="auto" や Freedman-Diaconis 則 (bins="fd") を試して比較すること。 - density=True を使うと Y軸が「密度」になり、KDE と重ねやすくなる。 - 複数グループを同じ axes に重ねるときは alpha=0.5 程度に設定し、seaborn の kdeplot か histplot(hue=...) を使うと見やすい。


5. 箱ひげ図 (Box Plot)

適用場面: 複数グループの分布を中央値・四分位範囲・ひげ・外れ値で比較する。

実装のポイント:

sns.boxplot(data=df, x="place_type", y="stress_score",
            palette=palette, ax=ax, order=[...])

箱の各要素の意味:

        ─── 上ひげ: Q3 + 1.5×IQR まで
    ┌───────┐
    │       │ ← Q3 (第3四分位数: 上位25%の境界)
    │───────│ ← 中央値 (Median)
    │       │ ← Q1 (第1四分位数: 下位25%の境界)
    └───────┘
        ─── 下ひげ: Q1 - 1.5×IQR まで
        ○   ← 外れ値 (ひげの外側)
    IQR = Q3 - Q1 (四分位範囲)

注意点: - 箱ひげ図は分布の形状(単峰・多峰・歪み)を表現できない。violin plot を代わりに使うか、個々のデータ点を stripplot で重ねると情報量が増す。 - order= を指定してカテゴリを意味のある順序(ストレスの低い順など)に並べると比較しやすい。


6. ヒートマップ (Heatmap)

適用場面: 相関行列や行×列の2次元集計表の値を色の濃淡で一覧する。

実装のポイント:

sns.heatmap(corr, cmap="RdBu_r", center=0, vmin=-1, vmax=1,
            annot=True, fmt=".2f", square=True)

注意点: - 色スケールは center=0 を設定し、正の相関(赤系)と負の相関(青系)を対称に表示する。RdBu_r や coolwarm が定番。 - annot=True で数値を表示するとき、変数が多い(10超)と文字が小さくなって読めなくなる。変数を絞るか annot_kws={"size": 6} で調整する。 - 相関行列は対称行列なので、上三角部分だけ表示する mask を使うと情報の重複が減る:

mask = np.triu(np.ones_like(corr, dtype=bool))
sns.heatmap(corr, mask=mask, ...)


グラフ選択フローの実践

問いを立てるときに、次の3つを確認する:

Step 1: 何を伝えたいか?
  ├─ 分布を見たい     → ヒストグラム / 箱ひげ図
  ├─ 比較したい       → 棒グラフ (カテゴリ) / 折れ線 (時系列)
  ├─ 関係を見たい     → 散布図 (2変数) / ヒートマップ (多変数)
  └─ 割合を見たい     → 積み上げ棒グラフ

Step 2: データの型は?
  ├─ 質的 + 量的      → 棒グラフ / 箱ひげ図
  ├─ 量的 + 量的      → 散布図 / ヒートマップ
  └─ 時間 + 量的      → 折れ線グラフ

Step 3: 比較対象の数は?
  ├─ 少ない (2〜5)    → 棒グラフ・折れ線が見やすい
  ├─ 中程度 (6〜15)   → ヒートマップ・散布図(色分け)
  └─ 多い (15+)       → ヒートマップ / FacetGrid での分割

コードの重要箇所解説

prepare_data() — 3種類の集計

summary = df.groupby("place_type")[numeric_cols].mean().reset_index()
weekly  = df.groupby(["week", "place_type"])["happiness_score"].mean().reset_index()
corr    = df[numeric_cols].corr()

groupby の引数をリストにすると複数列でグループ化できる。corr() は数値列の全ペアの Pearson 相関係数を一括計算する。

seaborn のテーマ設定

sns.set_theme(style="whitegrid", font_scale=0.9)

whitegrid はグリッド線が入る白背景スタイル。font_scale で全体のフォントサイズを調整できる。第01回の「データ-インク比」の観点からは ticks や white スタイルのほうが望ましい場合もある。

colorblind パレット

palette = sns.color_palette("colorblind", n_colors=5)

seaborn の "colorblind" パレットは Okabe-Ito に近い配色で、色覚多様性に配慮している。n_colors を指定することで必要な色数だけ取得できる。


今週の課題

exercise.py 内の演習問題 1〜5 を完成させてください。

  • 演習1: 3つのシナリオに対してグラフ種類を選択し、理由をコメントで記入する
  • 演習2: 棒グラフにエラーバー(標準誤差)を追加する
  • 演習3: 散布図に place_type の色分けを追加する
  • 演習4: カテゴリデータへの折れ線グラフの不適切さを判断し、棒グラフに書き直す
  • 演習5: 相関行列から注目変数を4つ選び、その理由を説明する

参考文献・リンク

  1. Wilke, C. O. (2019). Fundamentals of Data Visualization. O'Reilly Media.
    無料オンライン版: https://clauswilke.com/dataviz/
    — グラフ選択の判断基準が体系的にまとまった現代の標準テキスト。

  2. seaborn 公式ドキュメント — Example Gallery
    https://seaborn.pydata.org/examples/index.html

  3. matplotlib 公式ドキュメント — Plot types
    https://matplotlib.org/stable/plot_types/index.html

  4. Heer, J., & Bostock, M. (2010). Crowdsourcing graphical perception: Using Mechanical Turk to assess visualization design. CHI 2010.
    — 「人間はどのグラフ要素を正確に読めるか」を実験した古典論文。Cleveland & McGill の研究の現代的追試。

  5. Cleveland, W. S., & McGill, R. (1984). Graphical perception: Theory, experimentation, and application to the development of graphical methods. Journal of the American Statistical Association, 79(387), 531-554.
    — 散布図・棒グラフ・折れ線グラフの知覚精度の違いを示した古典。