0Pricing
Pandas & NumPy Academy · レッスン

外れ値の検出と処理

IQRによる境界とZスコアで外れ値を特定し、上限・下限で補正するか、削除するか、フラグを付けるかを判断して、決定内容を記録します。

「外れ値の検出と処理」はCoddyKit上の無料Pandas & NumPy Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはPandas & NumPy Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Pandas & NumPy Academyコースには全4レッスンが含まれています。

外れ値とは

外れ値とは、データセットの他のデータ点から大きく離れたデータ点です。外れ値には、データセット内の平均100ドルの注文の中にある、ある企業顧客の50万ドルの注文のように正しいものもあれば、負の価格や、120を12,000にしてしまったタイプミスのように誤ったものもあります。外れ値を処理する最初の段階は、その極端な値が実際に意味のあるものなのか、それともデータ品質の問題なのかを判断することです。どちらに該当するかで、処理方法は大きく異なります。

import pandas as pd
import numpy as np

df = pd.read_parquet('sales_clean.parquet')
print(df['revenue'].describe())

外れ値の可視化:箱ひげ図

箱ひげ図は、外れ値を見つけるための最も手早い可視化ツールです。箱は四分位範囲(IQR、Q1~Q3)を表し、ひげはIQRの1.5倍まで伸びます。ひげの外側にある点は、外れ値の候補として個別に表示されます。df['revenue'].plot(kind='box')またはSeabornのsns.boxplot()を使えば、しきい値を手作業で計算しなくても、外れ値をすぐに確認できます。

import matplotlib.pyplot as plt
import seaborn as sns

fig, ax = plt.subplots(figsize=(6, 4))
df['revenue'].plot(kind='box', ax=ax)
ax.set_title('Revenue Distribution — Box Plot')
plt.tight_layout()
plt.show()

IQRフェンス法

IQRフェンス法では、四分位範囲を計算し、Q1 − 1.5×IQRとQ3 + 1.5×IQRを境界値として定めます。この範囲の外側にある値を外れ値として扱います。1.5倍は軽度の外れ値に対する標準的な値で、極端な外れ値だけを検出する場合は3.0を使います。この方法は頑健です。Zスコアとは異なり、正規分布を仮定しません。

Q1 = df['revenue'].quantile(0.25)
Q3 = df['revenue'].quantile(0.75)
IQR = Q3 - Q1

lower = Q1 - 1.5 * IQR
upper = Q3 + 1.5 * IQR

outliers = df[(df['revenue'] < lower) | (df['revenue'] > upper)]
print(f'Q1={Q1:.0f}, Q3={Q3:.0f}, IQR={IQR:.0f}')
print(f'Bounds: [{lower:.0f}, {upper:.0f}]')
print(f'Outliers: {len(outliers)}')

外れ値検出のZスコア法

Zスコアは、値が平均から標準偏差何個分離れているかを表します。|Z| > 3の値は、通常、外れ値とみなされます。この基準は、正規分布するデータの99.7%をカバーします。ただし、Zスコアは検出しようとしている外れ値そのものの影響を受けやすいという欠点があります。極端な値によって平均が引き寄せられ、標準偏差が大きくなるため、他の外れ値が見えにくくなる可能性があります。

mean = df['revenue'].mean()
std = df['revenue'].std()

df['revenue_z'] = (df['revenue'] - mean) / std
z_outliers = df[df['revenue_z'].abs() > 3]

print(f'Z-score outliers (|z|>3): {len(z_outliers)}')
print(z_outliers[['revenue', 'revenue_z']].head())

外れ値のフラグ付けと削除

外れ値は、記録や根拠なしに削除してはいけません。まずはブール列(is_outlier)でフラグを付け、同じ地域、同じ商品、同じ日など、共通するパターンがあるかを分析します。正しい値であれば残し、モデル内で明示的に扱います。誤りであれば削除し、パイプラインの監査記録に削除件数を記録します。

df['is_revenue_outlier'] = (df['revenue'] < lower) | (df['revenue'] > upper)

print('Flagged rows:', df['is_revenue_outlier'].sum())
print(df.groupby('is_revenue_outlier')['revenue'].describe())

外れ値の上限・下限処理(Winsor化)

上限・下限処理(Winsor化)では、境界値を超えた値を削除するのではなく、その境界値自体に置き換えます。これにより、データセット内のすべての行を維持しながら、外れ値が線形モデルや要約統計量に与える歪みを抑えられます。clip(lower=, upper=)を使うと、1回のベクトル化処理で上限と下限を適用できます。

df['revenue_capped'] = df['revenue'].clip(lower=lower, upper=upper)

print('Original max:', df['revenue'].max())
print('Capped max:', df['revenue_capped'].max())
print('Rows changed:', (df['revenue'] != df['revenue_capped']).sum())

右に歪んだデータの対数変換

売上や価格の分布は、大きな値が長い裾を形成する右に歪んだ分布になることがよくあります。np.log1p()を使って対数変換すると、値に1を加えてから対数を取るため、0も扱いながら裾を圧縮し、分布をより対称にできます。多くの統計モデルや可視化では正規性が仮定されるため、モデル化の前に売上列を対数変換すると、結果が改善することがあります。

df['log_revenue'] = np.log1p(df['revenue'])

fig, axes = plt.subplots(1, 2, figsize=(12, 4))
df['revenue'].hist(bins=50, ax=axes[0])
axes[0].set_title('Original Revenue')
df['log_revenue'].hist(bins=50, ax=axes[1])
axes[1].set_title('Log Revenue')
plt.tight_layout()
plt.show()

複数列の外れ値

複数の列を一度に分析する場合は、すべての数値列についてプログラムでIQRによる外れ値の境界を計算します。数値列を順番に処理し、境界を計算して結果を辞書に保存します。これにより、列ごとにIQRの計算を手作業で繰り返さなくても、数行で外れ値の完全なレポートを作成できます。

numeric_cols = df.select_dtypes(include=['number']).columns

outlier_report = {}
for col in numeric_cols:
    Q1 = df[col].quantile(0.25)
    Q3 = df[col].quantile(0.75)
    IQR = Q3 - Q1
    n_out = ((df[col] < Q1 - 1.5*IQR) | (df[col] > Q3 + 1.5*IQR)).sum()
    outlier_report[col] = n_out

print(pd.Series(outlier_report).sort_values(ascending=False))

散布図による二変量外れ値

組み合わせによって初めて外れ値になるデータ点もあります。単価10ドルは通常の値で、数量500は珍しいものの不可能ではありません。しかし、高級品で単価10ドルかつ数量500となると、疑わしい値です。二変量外れ値は、散布図上で孤立した点として現れます。df.plot.scatter('quantity', 'unit_price')を使うと、主なデータのまとまりから離れた点を見つけられます。

fig, ax = plt.subplots(figsize=(8, 5))
df.plot.scatter(x='quantity', y='unit_price', alpha=0.3, ax=ax)
ax.set_title('Quantity vs. Unit Price — Bivariate Outliers')
plt.tight_layout()
plt.show()

外れ値に関する判断の記録

外れ値に関するすべての判断を記録してください。記録する内容は、列、検出方法、使用したしきい値、フラグを付けた行数、適用した処理(保持、上限・下限処理、削除)です。この記録があれば、コードレビューや監査で分析担当者の判断を説明できます。クリーニングログの辞書に保存し、出力データセットと一緒に保存してください。

outlier_log = {
    'column': 'revenue',
    'method': 'IQR 1.5x',
    'lower_bound': round(lower, 2),
    'upper_bound': round(upper, 2),
    'rows_flagged': int(df['is_revenue_outlier'].sum()),
    'treatment': 'cap (winsorise)'
}
for k, v in outlier_log.items():
    print(f'{k}: {v}')

処理済みデータセットの保存

外れ値にフラグを付けて処理したら、更新済みのDataFrameを保存します。下流の利用者が、目的に応じてフラグ付きの行を除外できるよう、出力にはis_outlierフラグ列を残してください。上限・下限処理後の値は、元の列と並べて、_cappedのような分かりやすいサフィックスを付けた列に保存します。こうすればクリーニングを元に戻せます。

cols_to_save = [c for c in df.columns if c not in ['revenue_z']]
df[cols_to_save].to_parquet('sales_treated.parquet', index=False)
print('Outlier-treated dataset saved:', df.shape)

確認テスト

このレッスンで学んだデータ分析の概念について、理解度を確認します。

レッスンのまとめ

このレッスンでは、IQRフェンス法とZスコアによる外れ値の検出、外れ値にフラグを付けるか、上限・下限処理をするか、削除するかの判断、そして右に歪んだ分布への対数変換の適用について学びました。次は、テキスト列内の一貫しないカテゴリラベルを標準化する方法について学びます。

よくある質問

「外れ値の検出と処理」レッスンは無料ですか?

はい。「外れ値の検出と処理」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Pandas & NumPy Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Pandas & NumPy Academyコースには全4レッスンが含まれています。

「外れ値の検出と処理」で何を学びますか?

IQRによる境界とZスコアで外れ値を特定し、上限・下限で補正するか、削除するか、フラグを付けるかを判断して、決定内容を記録します。 ブラウザで直接実行するハンズオンコードでPandas & NumPy Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Pandas & NumPy Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのPandas & NumPy Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。

「外れ値の検出と処理」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このPandas & NumPy Academyレッスンでコードを書いて実行できますか?

はい。すべてのPandas & NumPy Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. 重複の検出と削除
  2. 外れ値の検出と処理
  3. 不統一なカテゴリの標準化
  4. スキーマの検証とアサーション
← Pandas & NumPy Academyに戻る