Help us understand the problem. What is going on with this article?

箱ひげ図で外れ値になる確率を計算する

More than 3 years have passed since last update.

この記事の概要

  • 正規分布を仮定したときに、箱ひげ図における「外れ値」がどれぐらいの確率で出現するのかを調査
  • 「外れ値」の定義:第1四分位点-四分位範囲1.5 より小さい、または、第1四分位点-四分位範囲1.5 より大きい標本(極値も含んでます)
  • 「外れ値」が出現する確率は、およそ 0.70 %

この記事を書こうと思った動機

  • 業務で統計解析を行う際に、箱ひげ図を描いてみると、「外れ値」がよく出てくる
  • ある分布を仮定したときに、「外れ値」がどれぐらいの確率で出現するのかを知りたくなった

はじめに:箱ひげ図と外れ値

箱ひげ図および箱ひげ図における外れ値に関する説明は以下のサイトなどを参照してください。
- 箱ひげ図 - Wikipedia
- 箱ひげ図の読み方

正規分布における外れ値の出現確率を算出する

標準正規分布の確率密度関数を使って、外れ値となる確率を計算してみます。

import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from scipy import stats

q1_ideal = stats.norm.ppf(q=0.25, loc=mu, scale=sd) # 第1四分位点
q3_ideal = stats.norm.ppf(q=0.75, loc=mu, scale=sd) # 第3四分位点
iqr_ideal = q3_ideal-q1_ideal # 四分位範囲
lb_ideal = q1_ideal-1.5*iqr_ideal # 下側外れ値境界
ub_ideal = q3_ideal+1.5*iqr_ideal # 上側外れ値境界

print('Q1:', q1_ideal)
print('Q3:', q3_ideal)
print('IQR:', iqr_ideal)
print('Lower Bound:', lb_ideal)
print('Upper Bound:', ub_ideal)
print('下側外れ値となる確率:',stats.norm.cdf(x=lb_ideal, loc=mu, scale=sd) *100,'%')
print('上側外れ値となる確率:',stats.norm.sf(x=ub_ideal, loc=mu, scale=sd) *100,'%')
print('外れ値となる確率:',(stats.norm.sf(x=ub_ideal, loc=mu, scale=sd)+stats.norm.cdf(x=lb_ideal, loc=mu, scale=sd)) *100,'%')

>Q1: -0.674489750196
>Q3: 0.674489750196
>IQR: 1.34897950039
>Lower Bound: -2.69795900078
>Upper Bound: 2.69795900078
>下側外れ値となる確率: 0.348830161964 %
>上側外れ値となる確率: 0.348830161964 %
>外れ値となる確率: 0.697660323928 %

というわけで、正規分布であれば外れ値が得られる確率は、0.7%という結果です。1000個の標本があれば、7個ぐらいは外れ値となります。3σの外側に来るのが0.3%なので、それよりは多いですね。

実際にそうなっているか検証

正規分布からランダムサンプリングしたデータを使って、本当にそうなるのか確かめてみます。

# データ生成
n = 1000000 # サンプル数
mu = 0 # 平均
sd = 1 # 標準偏差
q1 = stats.scoreatpercentile(data, 25)
q3 = stats.scoreatpercentile(data, 75)
iqr = q3-q1
lb = q1-1.5*iqr
ub = q3+1.5*iqr
print('Q1:', q1)
print('Q2:', med)
print('Q3:', q3)
print('IQR:', iqr)
print('Lower Bound:', lb)
print('Upper Bound:', ub)
print('上側外れ値となった標本数の全標本数に占める割合:', len(np.where(data<lb)[0]) / n * 100,'%')
print('下側外れ値となった標本数の全標本数に占める割合:', len(np.where(data>ub)[0]) / n * 100,'%')
print('外れ値となった標本数の全標本数に占める割合:', (len(np.where(data>ub)[0])+len(np.where(data<lb))) / n * 100,'%')

>Q1: -0.674873830027
>Q2: -0.00106013590319
>Q3: 0.673290672641
>IQR: 1.34816450267
>Lower Bound: -2.69712058403
>Upper Bound: 2.69553742664
>上側外れ値となった標本数の全標本数に占める割合: 0.3554 %
>下側外れ値となった標本数の全標本数に占める割合: 0.3478 %
>外れ値となった標本数の全標本数に占める割合: 0.7032 %

ランダムサンプリングで計算した外れ値となる標本の割合は0.7%となり、確率密度関数から計算した値とほぼ一致しました。

yhyhyhjp
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした