Pandas & SciPyでトリム平均を算出!外れ値に強い統計量を使いこなす


 

データ分析において、平均値は最も基本的な統計量の一つですが、データに**外れ値(異常値)が含まれている場合、その平均値は外れ値に大きく影響され、データの真の傾向を反映しないことがあります。このような課題を解決するために役立つのがトリム平均(Trimmed Mean)**です。

トリム平均は、データをソートした後に、上下の一定割合のデータを除外してから計算される平均値です。これにより、外れ値の影響を排除し、よりロバスト(頑健)な平均値を得ることができます。

Pythonでは、科学計算ライブラリのSciPyがトリム平均を計算する機能を提供しており、PandasのDataFrameやNumPyのndarrayと組み合わせて効率的に利用できます。この記事では、トリム平均の概念から、SciPyを使った具体的な算出方法までを丁寧に解説します。


 

トリム平均(Trimmed Mean)とは?

 

トリム平均は、切断平均調整平均とも呼ばれます。計算手順は以下の通りです。

  1. データを昇順または降順にソートします。

  2. ソートされたデータの上下から、指定された割合(または個数)のデータを削除します。

  3. 残ったデータのみで算術平均を計算します。

例えば、上下10%のデータをトリムする場合、最も小さい10%のデータと、最も大きい10%のデータが計算から除外されます。これにより、極端な外れ値が平均値に与える影響を大幅に軽減できます。


 

SciPy trim_meanでトリム平均を算出

 

SciPyライブラリのscipy.stats.trim_mean関数を使用すると、簡単にトリム平均を計算できます。この関数はNumPy配列(ndarray)やPandas Series、DataFrameの列など、様々な数値データに対応しています。

 

基本的な使い方:Series/ndarrayの場合

 

まずは、外れ値を含むSeriesを使ってトリム平均を計算してみましょう。

Python
 
import pandas as pd
import numpy as np
from scipy.stats import trim_mean

# 外れ値を含むサンプルSeries
data_with_outliers = pd.Series([10, 12, 13, 15, 16, 18, 19, 20, 100, 5])
print("元のデータ:\n", data_with_outliers)
print("通常の平均:", data_with_outliers.mean())

# 上下10%をトリムして平均を計算
# proportioncut=0.1 は、各サイドからデータの10%を削除することを意味します。
trimmed_mean_10p = trim_mean(data_with_outliers, proportioncut=0.1)
print("\n上下10%をトリムした平均:", trimmed_mean_10p)

上記の例では、最も小さい5と最も大きい100がそれぞれ1つずつ(全10個のデータなので10%は1個)除外され、残りのデータで平均が計算されています。これにより、通常の平均値よりも外れ値の影響を受けにくい結果が得られます。

  • proportioncut: 各側(上下)から切り捨てるデータの割合(0.0から0.5の範囲)。例えば0.1なら、下位10%と上位10%が除外されます。

 

DataFrameの列に適用する

 

Pandas DataFrameの特定の列に対してトリム平均を適用することもできます。

Python
 
# サンプルDataFrameの作成
df = pd.DataFrame({
    'value_A': [10, 12, 15, 18, 200],
    'value_B': [5, 6, 7, 8, 9],
    'value_C': [30, 32, 35, 38, 40]
})
print("\n元のDataFrame:\n", df)

# 'value_A'列の上下20%をトリムした平均
# 5個のデータなので、20%は1個。上下1個ずつ除外されます。
trimmed_mean_A = trim_mean(df['value_A'], proportioncut=0.2)
print("\n'value_A'の上下20%トリム平均:", trimmed_mean_A)

# DataFrameの各列に一括適用 (applyメソッドを使用)
# 各列のSeriesがtrim_meanに渡されます
df_trimmed_means = df.apply(lambda x: trim_mean(x, proportioncut=0.2))
print("\nDataFrame各列の上下20%トリム平均:\n", df_trimmed_means)

DataFrameの例では、df.apply(lambda x: trim_mean(x, proportioncut=0.2))を使うことで、DataFrameの各列に対して一括でトリム平均を計算しています。


 

トリム平均の活用シーン

 

トリム平均は、以下のようなデータ分析のシナリオで特に有効です。

  • アンケート調査や評価データ: 回答者の誤入力や極端な意見(外れ値)が平均評価を歪めるのを防ぐ。

  • センサーデータやログデータ: 一時的なセンサーの誤作動やシステムエラーによる異常値の影響を排除し、安定した平均値を算出する。

  • ベンチマークテストの結果: 極端に速い/遅い実行時間を除外し、一般的なパフォーマンスを評価する。

  • 経済指標や市場データ: 短期的なパニック買い/売りなど、異常な市場変動の影響を除いた平均値を計算する。

 

注意点

 

  • データの損失: トリム平均はデータを一部除外するため、情報の一部が失われることに注意が必要です。除外する割合はデータの性質や分析の目的に応じて慎重に決定する必要があります。

  • 割合の選択: proportioncutの値をどれくらいにするかは、データの性質や外れ値の発生状況によって変わります。試行錯誤やドメイン知識に基づいて最適な割合を見つけることが重要です。


 

まとめ

 

PandasとSciPyのtrim_mean関数を組み合わせることで、データ中の外れ値に強い統計量であるトリム平均を効率的に算出できます。

  • トリム平均: データをソートし、上下の一定割合のデータを除外してから計算する平均値。

  • scipy.stats.trim_mean(data, proportioncut):

    • data: NumPy配列、Pandas Series、またはDataFrameの列。

    • proportioncut: 各側から切り捨てるデータの割合(0.0から0.5)。

  • 外れ値による平均値の歪みを軽減し、よりロバストなデータ分析を可能にする。

トリム平均は、外れ値が頻繁に発生する現実のデータを分析する上で非常に有用なツールです。ぜひ、ご自身のデータ分析に活用し、より正確な洞察を得る手助けにしてください!