異常値の検出
異常値は「常識的な範囲外の値」「平均から極端に離れた値」「分布の外側(箱ひげ基準)」など定義で取り方が変わります。初心者でも安心して使える、ルール閾値・Zスコア・IQR(箱ひげ)・移動基準の4方式を、実務テンプレと例題でまとめます。
選び方の指針
- まずは簡単に弾きたい: 固定の上下限(ルール閾値)
- 分布基準で汎用的に: Zスコア(平均±kσ)
- 外れ値に強い: IQR法(Q1−1.5IQR, Q3+1.5IQR)
- 時系列の突発検知: 移動平均/移動中央値+乖離
ルール閾値(上下限)の最短テンプレ
Sub Detect_Thresholds()
Dim last As Long: last = Cells(Rows.Count, "B").End(xlUp).Row 'B列が対象
Dim low As Double: low = 0
Dim high As Double: high = 100000
Dim r As Long
For r = 2 To last
Dim x As Double: x = Val(Cells(r, "B").Value)
If x < low Or x > high Then
Cells(r, "B").Interior.Color = RGB(255, 200, 200) '赤背景
Cells(r, "C").Value = "閾値外" 'C列にフラグ
End If
Next
End Sub
VB- ポイント:
- 仕様が明確な範囲(例:数量は0以上、金額は10万以下)に向く。
- 閾値は後から変更できるよう定数化しておくと楽。
Zスコア(平均±kσ)で異常値検出
Sub Detect_ZScore()
Dim rng As Range: Set rng = Range("B2:B" & Cells(Rows.Count, "B").End(xlUp).Row)
Dim mu As Double: mu = Application.WorksheetFunction.Average(rng)
Dim sd As Double: sd = Application.WorksheetFunction.StDev(rng) '標本標準偏差
If sd = 0 Then MsgBox "標準偏差が0のため判定不可": Exit Sub
Dim k As Double: k = 3 '3σルール
Dim r As Range
For Each r In rng
Dim z As Double: z = (Val(r.Value) - mu) / sd
If Abs(z) >= k Then
r.Interior.Color = RGB(255, 235, 156)
r.Offset(0, 1).Value = "Z≥" & k
End If
Next
End Sub
VB- ポイント:
- 分布が概ね正規に近いときに有効。
- kは2~3が実務の目安。sd=0の場合は全値同一なので判定できない。
IQR法(箱ひげ: Q1−1.5IQR, Q3+1.5IQR)
Sub Detect_IQR()
Dim rng As Range: Set rng = Range("B2:B" & Cells(Rows.Count, "B").End(xlUp).Row)
Dim q1 As Double: q1 = Application.WorksheetFunction.Quartile_Inc(rng, 1)
Dim q3 As Double: q3 = Application.WorksheetFunction.Quartile_Inc(rng, 3)
Dim iqr As Double: iqr = q3 - q1
Dim low As Double: low = q1 - 1.5 * iqr
Dim high As Double: high = q3 + 1.5 * iqr
Dim r As Range
For Each r In rng
Dim x As Double: x = Val(r.Value)
If x < low Or x > high Then
r.Font.Bold = True
r.Offset(0, 1).Value = "IQR外"
End If
Next
End Sub
VB- ポイント:
- 外れ値の影響を受けない堅牢な方法。分布が歪んでいても扱いやすい。
- Excelの環境によっては Quartile_Inc が使えない場合、Percentile_Inc で25%・75%を代替可能。
移動平均/移動中央値+乖離率(時系列の突発検知)
Sub Detect_RollingDeviation()
Dim last As Long: last = Cells(Rows.Count, "B").End(xlUp).Row
Dim window As Long: window = 7 '7件移動
Dim tol As Double: tol = 0.3 '30%乖離を異常扱い
Dim r As Long
For r = 2 + window To last
Dim base As Double: base = Application.WorksheetFunction.Median(Range(Cells(r - window, "B"), Cells(r - 1, "B")))
Dim x As Double: x = Val(Cells(r, "B").Value)
If base > 0 Then
Dim dev As Double: dev = Abs(x - base) / base
If dev >= tol Then
Cells(r, "B").Interior.Color = RGB(200, 255, 200)
Cells(r, "C").Value = "移動基準外"
End If
End If
Next
End Sub
VB- ポイント:
- 急激なスパイク/ドロップを検知。平均より中央値が外れ値に強く安定。
- tolは用途に応じて10~50%程度で調整。
爆速版:配列で一括計算→まとめて書き戻し
Sub Detect_IQR_ArrayFast()
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Application.EnableEvents = False
Dim rng As Range: Set rng = Range("B1").CurrentRegion.Columns(2) 'B列
Dim v As Variant: v = rng.Value
Dim q1 As Double: q1 = Application.WorksheetFunction.Quartile_Inc(rng.Offset(1, 0).Resize(rng.Rows.Count - 1), 1)
Dim q3 As Double: q3 = Application.WorksheetFunction.Quartile_Inc(rng.Offset(1, 0).Resize(rng.Rows.Count - 1), 3)
Dim iqr As Double: iqr = q3 - q1
Dim low As Double: low = q1 - 1.5 * iqr
Dim high As Double: high = q3 + 1.5 * iqr
Dim i As Long
For i = 2 To UBound(v, 1)
Dim x As Double: x = Val(v(i, 1))
If x < low Or x > high Then
'フラグ列(隣のC列に出す例)
Cells(rng.Row + i - 1, rng.Column + 1).Value = "IQR外"
End If
Next
Cleanup:
Application.Calculation = xlCalculationAutomatic
Application.EnableEvents = True
Application.ScreenUpdating = True
End Sub
VB- ポイント:
- 範囲→配列→判定→必要箇所だけ書き戻しで高速化。
- フォーマット変更(色付け)は Union 集合化→一括適用にするとさらに速い。
異常値の可視化(条件付き書式で補助)
Sub Visualize_WithCF()
With Range("B2:B" & Cells(Rows.Count, "B").End(xlUp).Row)
.FormatConditions.Delete
'上位1%を赤、下位1%を青(簡易)
.FormatConditions.AddTop10
.FormatConditions(.FormatConditions.Count).TopBottom = xlTop10Top
.FormatConditions(.FormatConditions.Count).Rank = 1
.FormatConditions(.FormatConditions.Count).Percent = True
.FormatConditions(.FormatConditions.Count).Interior.Color = RGB(255, 200, 200)
.FormatConditions.AddTop10
.FormatConditions(.FormatConditions.Count).TopBottom = xlTop10Bottom
.FormatConditions(.FormatConditions.Count).Rank = 1
.FormatConditions(.FormatConditions.Count).Percent = True
.FormatConditions(.FormatConditions.Count).Interior.Color = RGB(200, 200, 255)
End With
End Sub
VB- ポイント:
- コードを書かずに視覚的に外れを確認したいときに役立つ簡易法。
よくある落とし穴と対策
- 元データに文字列や空白が混じる
- 対策: Valで数値化、前処理でTrim/数値チェック(IsNumeric)を行う。
- 標準偏差が0でZスコア不可
- 対策: すべて同一値ならZスコアは無意味。IQR法や閾値法へ切り替える。
- 極端な外れ値が平均やσを歪める
- 対策: IQR法や移動中央値を使う。必要なら外れ値を除いて再推定。
- 時系列の季節性で誤検知
- 対策: 週次/月次など周期に合わせて窓幅を設定、または同曜日比較に変更。
- 演算対象の範囲がずれている
- 対策: CurrentRegionや見出し位置の自動取得で範囲を固定化。
例題で練習
'例1:B列をZスコア3σでマーキング
Sub Example_Z3Sigma()
Call Detect_ZScore
End Sub
'例2:B列をIQR法でフラグ付け、C列に「IQR外」
Sub Example_IQRFlag()
Call Detect_IQR
End Sub
'例3:B列の7件移動中央値から30%乖離を検知
Sub Example_RollingMedian()
Call Detect_RollingDeviation
End Sub
VB