データ分析において、データの分布の形や外れ値の有無を確認することは非常に重要です。「ヒストグラムの適切なbins設定が分からない」「箱ひげ図で外れ値がどう表現されているか理解したい」といった悩みはありませんか?本記事では、Python の Matplotlib と seaborn を用いてヒストグラムと箱ひげ図(Box Plot)を描く方法、bins の設計や IQR による外れ値検出・分析まで、データ分析の実践的な観点で初心者にも分かりやすく解説します。この記事を読めば、データの分布と外れ値を正確に把握し、より質の高いデータ分析ができるようになります。
この記事でわかること:データ分布の可視化と外れ値分析の完全ガイド
本記事では、データ分析初心者の方に向けて、データ分析において非常に重要な「データの分布」を理解するための主要な可視化手法であるヒストグラムと箱ひげ図(Box Plot)に焦点を当てて解説します。これらのグラフは、単にデータを可視化するだけでなく、顧客の購買傾向の把握(どの価格帯の商品がよく売れるか、売上の分布)、製品の品質管理(製品のばらつきは許容範囲か、不良品の特定)、マーケティング施策の効果測定(施策前後で顧客の反応分布はどう変わったか、効果の偏り)など、様々なビジネスや研究の課題解決に役立ちます。さらに、これらの図を通してデータの偏りや外れ値を視覚的に捉えることが、より正確な分析には不可欠です。
具体的には、Python の主要なデータ可視化ライブラリである Matplotlib と seaborn を使って、以下の内容を学ぶことができます。
- ヒストグラムの基本: データの度数分布を視覚化する。
- bins の適切な決め方: ヒストグラムの見た目を左右する bins 設定(auto / sturges / fd ほか)の使い分けと特徴。データ分析初心者にも分かりやすい解説を心がけます。ヒストグラムの解釈力を高めます。
- 密度表示と重ね描き: 異なるグループ間での分布比較に役立つテクニック(
density=True
,histtype="step"
)。データ分布の比較をより正確に行います。 - 箱ひげ図の仕組み: 中央値、四分位数、ひげ、外れ値といった主要な要素の理解。箱ひげ図からデータの要約情報を読み取ります。
- 箱ひげ図の応用:
whis
,showmeans
,patch_artist
などのオプションで詳細を表示。箱ひげ図をカスタマイズして分析を深めます。 - IQR(四分位範囲)による外れ値検出と可視化: 統計的な手法で外れ値を特定し、ヒストグラムと組み合わせてグラフ上で明確に示す方法。異常値検出の重要な手法です。
これらの可視化手法と外れ値分析を通じて、データ分析の基礎を習得し、データの分布や特徴をより深く理解することできます。
▶️ Matplotlib の公式ドキュメントも参考にしてください:
ヒストグラム 箱ひげ図1. ヒストグラムの基本とデータ準備:データ分布の全体像を掴む
データ分析の第一歩として、データの全体像を掴むことは非常に重要です。そのために最もよく用いられるグラフの一つがヒストグラムです。ヒストグラムは、データをいくつかの区間(ビン、階級)に分け、それぞれの区間に含まれるデータの個数(度数)を棒グラフで表現することで、データの分布の形状、データの集中度、歪み、ピークの数などを視覚的に捉えることができます。これはデータ分析における基本的な可視化手法です。
ここでは、Python のデータ可視化ライブラリである Matplotlib を用いたヒストグラムの基本的な描画方法を見ていきましょう。データの前処理や確認には、pandas ライブラリを使用します。
本記事では、例として seaborn ライブラリに組み込まれている tips
データセットを使用します。このデータセットには、あるレストランでのチップに関する情報(合計金額、チップ額、性別、喫煙の有無、曜日、時間帯、人数)が含まれており、データ分析の練習によく用いられます。このデータセットを使って、合計金額やチップ額の分布を分析してみましょう。このデータセットは広く利用されており、データ分析の学習に適しています。
import numpy as np # numpyをインポート
import matplotlib.pyplot as plt
import pandas as pd # pandasをインポート
import seaborn as sns # seabornをインポートしてtipsデータセットを使用
import japanize_matplotlib # Google Colab の機能を使って日本語フォントをインストール・インポート
!pip install japanize-matplotlib > /dev/null
# tipsデータセットを読み込む
tips_df = sns.load_dataset("tips")
display(tips_df)
fig, ax = plt.subplots()
# tips_dfの"total_bill"列を指定してヒストグラムを描画
ax.hist(tips_df["total_bill"], bins=20, color="skyblue", edgecolor="white")
ax.set_title("合計金額のヒストグラム")
ax.set_xlabel("合計金額")
ax.set_ylabel("度数")
plt.show()
total_bill | tip | sex | smoker | day | time | size | |
---|---|---|---|---|---|---|---|
0 | 16.99 | 1.01 | Female | No | Sun | Dinner | 2 |
1 | 10.34 | 1.66 | Male | No | Sun | Dinner | 3 |
2 | 21.01 | 3.50 | Male | No | Sun | Dinner | 3 |
3 | 23.68 | 3.31 | Male | No | Sun | Dinner | 2 |
4 | 24.59 | 3.61 | Female | No | Sun | Dinner | 4 |
… | … | … | … | … | … | … | … |
239 | 29.03 | 5.92 | Male | No | Sat | Dinner | 3 |
240 | 27.18 | 2.00 | Female | Yes | Sat | Dinner | 2 |
241 | 22.67 | 2.00 | Male | Yes | Sat | Dinner | 2 |
242 | 17.82 | 1.75 | Male | No | Sat | Dinner | 2 |
243 | 18.78 | 3.00 | Female | No | Thur | Dinner | 2 |
244 rows × 7 columns
ax.hist()
は、デフォルトでは階級(bin)の数や範囲をデータから自動で推定してくれます。しかし、bin の設定によってヒストグラムの見え方は大きく変わるため、より詳細に分布を把握するには調整が必要です。データ分析の目的に合わせて最適な bin 設定を選択することが重要です。細かく調整したい場合は次章を参照してください。ヒストグラムの解釈においては、bin の設定が鍵となります。
2. bins 設計:ヒストグラムの見え方を左右する階級設定の重要性
前章では基本的なヒストグラムを描画しましたが、ヒストグラムの見え方は bin の数で大きく変わります。bin の数が少なすぎると大まかすぎて特徴(データの山や谷、歪みなど)が見えにくくなり、多すぎるとノイズが多くてかえって分かりにくくなることがあります。データ分析の性質や分析の目的に合わせて適切な bin の数を選ぶことは、ヒストグラムからデータの分布を正しく読み取る上で非常に重要です。
本章では、Matplotlib が提供する bins
の様々な設定方法と、それぞれのルールの特徴について解説します。tips
データセットの total_bill
列を使って、データの性質や目的に合わせて最適な bins
の設定を選べるようになりましょう。これらの異なる設定でヒストグラムを比較することで、bins
が分布の見え方に与える影響を理解できます。効果的なデータ可視化のための重要なステップです。
fig, axs = plt.subplots(1, 3, figsize=(9, 3), constrained_layout=True)
fig.suptitle("異なる bins 設定のヒストグラム比較(合計金額)", fontsize=16) # 大きなタイトルを追加
data_to_plot = tips_df["total_bill"] # tips_dfのtotal_bill列を使用
axs[0].hist(data_to_plot, bins="sturges", color="steelblue", edgecolor="white")
axs[0].set_title("bins='sturges'")
axs[1].hist(data_to_plot, bins="fd", color="steelblue", edgecolor="white")
axs[1].set_title("bins='fd'(Freedman–Diaconis)")
axs[2].hist(data_to_plot, bins="auto", color="steelblue", edgecolor="white")
axs[2].set_title("bins='auto'")
for ax in axs:
ax.set_xlabel("合計金額"); ax.set_ylabel("度数")
plt.show()
- “sturges”:サンプル数が少ないときに過度に細かくなりにくい
- “fd”:IQRに基づき、外れ値に比較的ロバスト
- “auto”:状況に応じて良い感じに調整(便利な初期値)
コツ:まず”auto”で傾向を見て、必要なら”fd”や整数値(例:bins=30)に固定して比較します。
3. 密度表示・重ね描き・ステップ表示
ヒストグラムは度数で表示するのが基本ですが、異なるデータセットの分布を比較したい場合など、データの総数が異なる場合には、度数ではなく確率密度として表示する方が適切なケースがあります。また、複数のデータセットの分布を一度に比較するために、ヒストグラムを重ねて描くことも有効です。
ここでは、①density=True
オプションを使った密度表示や、複数のヒストグラムを重ねて描く方法、そして ②histtype="step"
を用いたステップ表示について、tips
データセットの喫煙者と非喫煙者のチップ額を比較する例で紹介します。これらのテクニックを使うことで、より柔軟にデータの分布を比較・分析できるようになります。
なぜ密度表示を使うのか?異なるグループの分布比較の利点
ヒストグラムは通常、各区間のデータ数(度数)を示しますが、異なるデータセットやグループの分布を比較したい場合、データの総数(サンプルサイズ)が異なると、度数分布では正確な比較が難しくなります。データ総数が多いグループほど、単純にバーが高くなるためです。例えば、喫煙者と非喫煙者でチップ額の分布を比較したいとき、それぞれの人数が異なると、単純な度数ヒストグラムでは人数の多いグループのバーが高くなり、分布の「形」そのものを比較しにくくなります。
density=True
オプションを使うと、ヒストグラムの各ビンのデータ数を全データ数で割った相対度数、さらにビンの幅で割った密度が表示されます。これにより、ヒストグラムの全ビンの面積の合計が 1 となり、グループのサンプルサイズの違いに影響されずに、分布の形状やデータの相対的な集中度を比較できるようになります。これは、データの「相対的な起こりやすさ」を示す方法と考えることができます。
特に、今回の喫煙者と非喫煙者のように、比較したいグループの人数が異なる場合には、密度分布で表示する方が分布の傾向をより適切に比較できます。これにより、「どちらのグループの方が、ある金額範囲のチップを支払う傾向が強いか」といったデータ分析における洞察を得やすくなります。ぜひ、ご自身のデータでも試してみてください!
# 喫煙者と非喫煙者にデータを分割
# tips_dfはすでに読み込まれているものとします。
tips_smoker = tips_df[tips_df["smoker"] == "Yes"]["tip"]
tips_non_smoker = tips_df[tips_df["smoker"] == "No"]["tip"]
fig, ax = plt.subplots()
ax.hist(tips_smoker, bins="auto", density=True, alpha=0.6, label="喫煙者")
ax.hist(tips_non_smoker, bins="auto", density=True, alpha=0.6, label="非喫煙者")
ax.set_title("喫煙・非喫煙別のチップ額密度分布")
ax.set_xlabel("チップ額"); ax.set_ylabel("密度")
ax.legend()
plt.show()
このヒストグラムから、喫煙者と非喫煙者の間でチップ額の分布にわずかな違いがある可能性が読み取れます。どちらのグループもチップ額が低い方にピークがありますが、喫煙者の方が非喫煙者よりもやや高いチップを支払う傾向が見られる区間があります。これは、喫煙者の方がチップ額のばらつきがやや大きいことを示唆しているとも言えます。ただし、これはあくまでグラフから見た傾向であり、この違いが単なる偶然ではないか(統計的に意味のある違いか)を判断するには、別途統計的な手法を使った確認が必要です。データ分析においては、このような視覚的な傾向を掴むことが重要です。
線だけで表示するにはhisttype=”step”を使います。
import matplotlib.pyplot as plt
import seaborn as sns
import japanize_matplotlib
# 喫煙者と非喫煙者にデータを分割 (すでに分割している場合は不要)
# tips_smoker = tips_df[tips_df["smoker"] == "Yes"]["tip"]
# tips_non_smoker = tips_df[tips_df["smoker"] == "No"]["tip"]
fig, ax = plt.subplots()
ax.hist(tips_smoker, bins=20, density=True, histtype="step", label="喫煙者")
ax.hist(tips_non_smoker, bins=20, density=True, histtype="step", label="非喫煙者")
ax.set_title("喫煙・非喫煙別のチップ額密度分布 (ステップ表示)")
ax.set_xlabel("チップ額"); ax.set_ylabel("密度")
ax.legend()
plt.show()
4. 箱ひげ図の基本:データ分布の要約と外れ値の特定方法
ヒストグラムがデータの分布全体(形状、ピーク、歪みなど)を把握するのに適しているのに対し、箱ひげ図(Box Plot)は、データの中心的な傾向、ばらつき、そして外れ値を簡潔に視覚的に捉えるのに便利なツールです。特に複数のグループ間や異なる変数間でデータの分布を比較する際にその威力を発揮します。箱ひげ図を見ることで、データの中央値、ばらつきの範囲(四分位範囲)、データの偏り(歪み)、そして「ひげ」の範囲を超える外れ値を一目で確認できます。これはデータ分析における重要な可視化手法です。
ここでは、箱ひげ図の基本的な見方(中央値、四分位数、ひげ、外れ値が何を意味するのか)と、Matplotlib を用いて描画する方法を学びます。tips
データセットを使って、曜日ごとの合計金額の分布を箱ひげ図で確認してみましょう。ヒストグラムと合わせて使うことで、データの理解がさらに深まり、より多角的なデータ分析が可能になります。データサイエンスにおける必須の可視化手法です。
import matplotlib.pyplot as plt
import seaborn as sns
import japanize_matplotlib # 日本語表示のため
fig, ax = plt.subplots()
sns.boxplot(x="day", y="total_bill", data=tips_df, ax=ax, palette="viridis")
ax.set_title("曜日ごとの合計金額の箱ひげ図")
ax.set_xlabel("曜日")
ax.set_ylabel("合計金額")
plt.show()
/tmp/ipython-input-191451854.py:6: FutureWarning: Passing `palette` without assigning `hue` is deprecated and will be removed in v0.14.0. Assign the `x` variable to `hue` and set `legend=False` for the same effect. sns.boxplot(x="day", y="total_bill", data=tips_df, ax=ax, palette="viridis")
この箱ひげ図から、曜日ごとの合計金額の分布についていくつかの点が読み取れます。
- 中央値とばらつき: 土曜日と日曜日は中央値が他の曜日よりも高く、合計金額のばらつき(箱の長さ)も大きい傾向があります。これは、週末の方が比較的利用金額が高い顧客が多いことを示唆している可能性があります。
- 外れ値: 特に木曜日、土曜日、日曜日に比較的高い合計金額の外れ値が見られます。これは、その曜日に高額な飲食をしたグループが存在したことを示しています。これらの外れ値はデータ分析において注意が必要です。
- 分布の形状: 木曜日と金曜日に比べて、土曜日と日曜日は箱(データの中心 50%)がより高い位置にあり、合計金額の分布が全体的に高くなっていることが視覚的に確認できます。
これらの情報から、このレストランでは週末(特に土・日)に客単価が高くなる傾向があり、外れ値も週末に発生しやすいことが分かります。データ分析の次のステップとして、これらの傾向をさらに深掘りすることができます。
5. 箱ひげ図の応用オプション:詳細表示とカスタマイズで分析を深める
基本の箱ひげ図に加えて、Matplotlib は様々なオプションを提供しており、より詳細な情報を表示したり、見た目を調整したりすることが可能です。これらのオプションを使いこなすことで、箱ひげ図から得られる情報を増やし、より効果的なデータ分析を行うことができます。例えば、ひげの定義を変えたり、平均値を強調したり、箱の色をカスタマイズしたりすることで、特定の分析目的に合わせた箱ひげ図を作成できます。データ分布の理解を深めるための重要なテクニックです。
本章では、ひげの長さを制御する whis
(IQR の何倍までをひげとするか)、平均を表示する showmeans
、箱を塗りつぶして色を変えやすくする patch_artist
などの主なオプションの使い方を見ていきます。tips
データセットの曜日ごとの合計金額の箱ひげ図にこれらのオプションを適用してみましょう。これらのオプションを使うことで、箱ひげ図からより多くの情報を読み取り、データの特性を深く理解することができます。データ可視化スキルの向上に繋がります。
import matplotlib.pyplot as plt
import seaborn as sns
import japanize_matplotlib # 日本語表示のため
fig, ax = plt.subplots()
bp = sns.boxplot(x="day", y="total_bill", data=tips_df, ax=ax, palette="viridis", hue="day", legend=False,
whis=1.5, # ひげの長さ(IQR何倍か)
showmeans=True, # 平均を表示
patch_artist=True) # 長方形を塗りつぶし可能に
# 色付け(patch_artist=Trueが必要)
colors = ["#87CEEB", "#FFA500", "#90EE90", "#FFB6C1"] # 各曜日に色を割り当て
# 箱のパッチを取得して色付け
for i, patch in enumerate(ax.artists):
# Axes.artists に箱のPatchが含まれています
patch.set_facecolor(colors[i % len(colors)])
ax.set_title("曜日ごとの合計金額の箱ひげ図(オプション付き)")
ax.set_xlabel("曜日")
ax.set_ylabel("合計金額")
plt.show()
showfliers=False で外れ値マーカーを表示しない設定も可能です。スタイルは flierprops や meanprops などで細かく変更できます。これらのオプションを使いこなすことで、箱ひげ図をより効果的に活用できます。
6. IQR で外れ値を検出してヒストグラムと合わせて可視化:異常値の特定と分析
箱ひげ図でも外れ値を確認できますが、IQR(四分位範囲)を用いた統計的な計算によって、プログラムで明確に外れ値を定義し、ヒストグラムと合わせて可視化することも可能です。外れ値はデータ分析において、集計結果やモデル構築に大きな影響を与える可能性のある要素であり、適切に検出・処理することが重要です。IQR は、データの中心的な 50% が存在する範囲を示すため、この範囲から大きく外れたデータを外れ値として定義するのに一般的に用いられます。これは異常値検出の基本的な手法です。
本章では、IQR を使って外れ値を検出し、元のデータのヒストグラムと合わせて表示する方法を解説します。ここでは、tips
データセットの total_bill
列を使って外れ値を検出してみましょう。これにより、データの分布の中で特に注目すべき外れ値を明確に把握し、その位置や他のデータとの関係性を視覚的に理解できるようになります。外れ値がデータのどのあたりに存在するのかをヒストグラム上で確認することは、その後のデータ分析方針を立てる上で非常に役立ちます。
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd # pandasをインポート
import seaborn as sns # seabornをインポート
import japanize_matplotlib # 日本語表示のため
# tipsデータセットのtotal_bill列を使用し、変数名を変更
total_bill_data = tips_df["total_bill"]
# 四分位とIQRを計算
q1 = total_bill_data.quantile(0.25)
q3 = total_bill_data.quantile(0.75)
iqr = q3 - q1
# 外れ値の閾値を計算 (IQRの1.5倍)
lower = q1 - 1.5 * iqr
upper = q3 + 1.5 * iqr
# IQRの閾値に基づいて外れ値を特定
outliers_tips = total_bill_data[(total_bill_data < lower) | (total_bill_data > upper)]
fig, ax = plt.subplots(figsize=(8,5))
# ヒストグラムを描画
counts, bins, patches = ax.hist(total_bill_data, bins="auto", color="lightcoral", edgecolor="white", alpha=0.8)
# IQRの閾値を垂直線で表示
ax.axvline(lower, color="blue", linestyle="--", label=f"下限 {lower:.2f}")
ax.axvline(upper, color="blue", linestyle="--", label=f"上限 {upper:.2f}")
# 外れ値に点を打つ (ヒストグラムの最大度数より少し上の位置にプロット)
# 外れ値がない場合はプロットしないように条件分岐を追加
if len(outliers_tips) > 0:
# ヒストグラムの最大度数を取得し、外れ値をその少し上の位置にプロット
max_count = max(counts) if len(counts) > 0 else 0
ax.scatter(outliers_tips, np.full_like(outliers_tips, max_count * 1.05), color='red', zorder=5, label="外れ値")
ax.set_title("IQRによる合計金額の外れ値検出")
ax.set_xlabel("合計金額")
ax.set_ylabel("度数")
ax.legend()
plt.show()
この図から、IQR(四分位範囲)を用いた計算によって検出された合計金額の外れ値が、上限閾値(約 40.30 ドル)を超える比較的高い金額のデータ点であることが明確に分かります。下限閾値(約-2.82 ドル)を下回るデータ点はありませんでした。赤色の点が外れ値としてプロットされており、ヒストグラムの分布の右端、つまり高額な合計金額の領域に位置していることが視覚的に確認できます。
これにより、tips
データセットにおける合計金額の外れ値は、少数の非常に高額な支払いに起因している可能性が高いことが示唆されます。これらの外れ値がデータ分析(例えば平均値の計算や回帰分析など)にどのような影響を与えるかを検討し、必要に応じて外れ値の除外や変換といった対処をすることが重要です。外れ値の原因を探ることも、ビジネス上の示唆を得る上で valuable です。異常値分析はデータ分析において不可欠なステップです。
- IQR 法の注意:分布が強く歪んでいると外れ値が多く検出されることがあります。whis 倍率の調整や、対数スケールの検討も有効です。データ分析の際には、データの特性に合わせて手法を選択することが重要です。
まとめ:ヒストグラムと箱ひげ図でデータ分布を深く理解する
本記事では、データ分析初心者の方に向けて、データ分析の基本であるヒストグラムと箱ひげ図について、その使い方とデータからより多くの情報を引き出すためのテクニックを学びました。これらのグラフを使いこなすことで、データの隠れた特徴やパターンを発見し、より深い洞察を得ることができるようになります。
- ヒストグラムは
bins
の設定でデータの見え方が大きく変わります。まずは"auto"
で傾向を掴み、必要に応じて"fd"
や具体的な整数値で調整しましょう。効果的なデータ可視化の鍵となります。 - 異なるグループ間の分布を比較する際は、
density=True
による密度表示やhisttype="step"
が便利です。 - 箱ひげ図は、中央値、四分位数、ひげ、そして外れ値をコンパクトに表現するのに優れています。
whis
や色の調整 (patch_artist=True
) を使うことで、表示をカスタマイズできます。 - IQR(四分位範囲)を用いると、統計的に外れ値を定義し、ヒストグラムなどに閾値や外れ値の点を示すことで、データの異常値を明確に可視化できます。外れ値検出の基本です。
これらのグラフを使いこなすことで、データの基本的な性質、データの集中している範囲、ばらつきの度合い、そして注意すべき外れ値といったデータの隠れた特徴やパターンを発見し、ビジネスや研究における意思決定の質を高めることができるでしょう。データ分析の次のステップとして、これらの可視化スキルをぜひ活用してください。データサイエンスの学習を続ける上で、これらの知識は不可欠です。

コメント