LoginSignup
2
1

More than 5 years have passed since last update.

Pythonでパーセンタイル値を計算をする

Last updated at Posted at 2018-09-29

概要

Pythonでパーセンタイル値の計算をします。

パーセンタイルの明確な定義無いため実装方法も複数あるようですが、計算方法が違っていても、大量のデータで計算した場合有意な差にはならないとのこと。

今回は下記のサイトを参考に実装しました。また、numpyを用いた方法も紹介します。
http://marketer-thinking.com/statistics/data2.html

実装


def calc_pt(values, pt):
    """
    パーセンタイル値を計算する
    """
    import math
    # 求めるパーセンタイル値がリストの何番目の要素か
    order = (len(values) + 1) * (pt / 100)
    # 小数部と整数部に分ける
    f, i = math.modf(order)
    sorted_vals = sorted(values)
    # math.modf()はfloatで結果が返るのでキャスト
    i = int(i)
    return sorted_vals[i-1] + f * (sorted_vals[i-1] - sorted_vals[i])


def calc_pt_numpy(values, pt):
    """
    numpyでパーセンタイル値を計算する
    """
    import numpy
    return numpy.percentile(numpy.array(values), pt)


def main():
    """
    メイン処理の実行
    """
    import random
    for n in [100, 10000, 1000000]:
        values = []
        for _ in range(n):
            values.append(random.uniform(0.0, 100.0))

        # パーセンタイル値を計算
        for pt in [50, 80, 90, 99]:
            my_pt = calc_pt(values, pt)
            numpy_pt = calc_pt_numpy(values, pt)
            print("n={}, my_pt={}, numpy_pt={}, ratio={}".format(
                n, my_pt, numpy_pt, my_pt/numpy_pt
            ))
        print()


if __name__ == '__main__':
    main()

実行結果

n=100, my_pt=59.334260375137355, numpy_pt=59.41420584791042, ratio=0.9986544384186888
n=100, my_pt=83.55682075034058, numpy_pt=83.73113216533889, ratio=0.9979182006681324
n=100, my_pt=86.45906782186731, numpy_pt=89.49530919428327, ratio=0.9660737372746022
n=100, my_pt=97.24633378796958, numpy_pt=98.2281366779185, ratio=0.9900048710771318

n=10000, my_pt=49.94757837390801, numpy_pt=49.95727347919067, ratio=0.999805932057387
n=10000, my_pt=80.35364111790138, numpy_pt=80.35485783190325, ratio=0.9999848582396298
n=10000, my_pt=90.1259765722587, numpy_pt=90.15243353511485, ratio=0.9997065307965775
n=10000, my_pt=98.96393575713691, numpy_pt=98.9824941131185, ratio=0.9998125087052223

n=1000000, my_pt=49.985451493835484, numpy_pt=49.98563688434545, ratio=0.9999962911243804
n=1000000, my_pt=80.01341181661982, numpy_pt=80.01344482978872, ratio=0.9999995874047296
n=1000000, my_pt=90.00047774373063, numpy_pt=90.00065066573823, ratio=0.9999980786582505
n=1000000, my_pt=98.99860932658436, numpy_pt=98.99886918947561, ratio=0.999997375092328

numpyで計算したパーセンタイルと一致しませんが、nが大きくなるほど、差異が小さくなっていることがわかります。

疑問

データ数とパーセンタイルによっては、リストのインデックスを超えることになるが、どうすれば良いのか。

例えば、今回の実装ではデータ数が10でパーセンタイルが99を求めることができない。

2
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1