回答:
SciPy Statsパッケージに興味があるかもしれません。それはあなたが求めているパーセンタイル関数と他の多くの統計的な良さを持っています。
percentile()
利用可能であるにnumpy
すぎ。
import numpy as np
a = np.array([1,2,3,4,5])
p = np.percentile(a, 50) # return 50th percentile, e.g median.
print p
3.0
このチケットは、percentile()
すぐにそれらがnumpy に統合されないことを私に信じさせます。
df.groupby('key')[['value']].agg(lambda g: np.percentile(g, 10))
ちなみに、scipyに依存したくない場合のために、パーセンタイル関数の純粋なPython実装があります。関数は以下にコピーされます:
## {{{ http://code.activestate.com/recipes/511478/ (r1)
import math
import functools
def percentile(N, percent, key=lambda x:x):
"""
Find the percentile of a list of values.
@parameter N - is a list of values. Note N MUST BE already sorted.
@parameter percent - a float value from 0.0 to 1.0.
@parameter key - optional key function to compute value from each element of N.
@return - the percentile of the values
"""
if not N:
return None
k = (len(N)-1) * percent
f = math.floor(k)
c = math.ceil(k)
if f == c:
return key(N[int(k)])
d0 = key(N[int(f)]) * (c-k)
d1 = key(N[int(c)]) * (k-f)
return d0+d1
# median is 50th percentile.
median = functools.partial(percentile, percent=0.5)
## end of http://code.activestate.com/recipes/511478/ }}}
percentile
ように使用するN
かをどのようにして知るのですか?関数呼び出しでは指定されていません。
N
すると、パーセンタイルを計算する前にデータを変換できます。実際にタプルのリストがあり、タプルの最初の要素のN = [(1, 2), (3, 1), ..., (5, 1)]
パーセンタイルを取得する場合は、を選択します。また、パーセンタイルを計算する前に、リスト要素に(順序を変更する)変換を適用することもできます。key=lambda x: x[0]
numpyを使わずにpythonのみを使用してパーセンタイルを計算する方法は次のとおりです。
import math
def percentile(data, percentile):
size = len(data)
return sorted(data)[int(math.ceil((size * percentile) / 100)) - 1]
p5 = percentile(mylist, 5)
p25 = percentile(mylist, 25)
p50 = percentile(mylist, 50)
p75 = percentile(mylist, 75)
p95 = percentile(mylist, 95)
通常パーセンタイルの定義は、結果として、指定されたリストの値からPパーセントの値が見つかるという結果を期待しています...つまり、結果はセット要素間の補間ではなく、セットからのものでなければなりません。これを取得するには、より単純な関数を使用できます。
def percentile(N, P):
"""
Find the percentile of a list of values
@parameter N - A list of values. N must be sorted.
@parameter P - A float value from 0.0 to 1.0
@return - The percentile of the values.
"""
n = int(round(P * len(N) + 0.5))
return N[n-1]
# A = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
# B = (15, 20, 35, 40, 50)
#
# print percentile(A, P=0.3)
# 4
# print percentile(A, P=0.8)
# 9
# print percentile(B, P=0.3)
# 20
# print percentile(B, P=0.8)
# 50
提供されたリストから、値のPパーセント以下の値を取得する場合は、次の簡単な変更を使用します。
def percentile(N, P):
n = int(round(P * len(N) + 0.5))
if n > 1:
return N[n-2]
else:
return N[0]
または、@ ijustlovemathによって提案された簡略化を使用して:
def percentile(N, P):
n = max(int(round(P * len(N) + 0.5)), 2)
return N[n-2]
PERCENTILE
関数は、あなたの上部の例については、以下のパーセンタイルを返します3.7 = percentile(A, P=0.3)
、0.82 = percentile(A, P=0.8)
、20 = percentile(B, P=0.3)
、42 = percentile(B, P=0.8)
。
n = int(...)
、をmax(int(...), 1)
関数でラップすることです
以降Python 3.8
、標準ライブラリにはquantiles
、statistics
モジュールの一部として関数が付属しています。
from statistics import quantiles
quantiles([1, 2, 3, 4, 5], n=100)
# [0.06, 0.12, 0.18, 0.24, 0.3, 0.36, 0.42, 0.48, 0.54, 0.6, 0.66, 0.72, 0.78, 0.84, 0.9, 0.96, 1.02, 1.08, 1.14, 1.2, 1.26, 1.32, 1.38, 1.44, 1.5, 1.56, 1.62, 1.68, 1.74, 1.8, 1.86, 1.92, 1.98, 2.04, 2.1, 2.16, 2.22, 2.28, 2.34, 2.4, 2.46, 2.52, 2.58, 2.64, 2.7, 2.76, 2.82, 2.88, 2.94, 3.0, 3.06, 3.12, 3.18, 3.24, 3.3, 3.36, 3.42, 3.48, 3.54, 3.6, 3.66, 3.72, 3.78, 3.84, 3.9, 3.96, 4.02, 4.08, 4.14, 4.2, 4.26, 4.32, 4.38, 4.44, 4.5, 4.56, 4.62, 4.68, 4.74, 4.8, 4.86, 4.92, 4.98, 5.04, 5.1, 5.16, 5.22, 5.28, 5.34, 5.4, 5.46, 5.52, 5.58, 5.64, 5.7, 5.76, 5.82, 5.88, 5.94]
quantiles([1, 2, 3, 4, 5], n=100)[49] # 50th percentile (e.g median)
# 3.0
quantiles
与えられた分布に対して、分位点間隔を分割するカットポイントのdist
リストを返します(等確率の連続間隔への分割)。n - 1
n
dist
n
statistics.quantiles(dist、*、n = 4、method = 'exclusive')
ここn
で、私たちの場合(percentiles
)は100
です。
シリーズのパーセンタイルを計算するには、次のコマンドを実行します。
from scipy.stats import rankdata
import numpy as np
def calc_percentile(a, method='min'):
if isinstance(a, list):
a = np.asarray(a)
return rankdata(a, method=method) / float(len(a))
例えば:
a = range(20)
print {val: round(percentile, 3) for val, percentile in zip(a, calc_percentile(a))}
>>> {0: 0.05, 1: 0.1, 2: 0.15, 3: 0.2, 4: 0.25, 5: 0.3, 6: 0.35, 7: 0.4, 8: 0.45, 9: 0.5, 10: 0.55, 11: 0.6, 12: 0.65, 13: 0.7, 14: 0.75, 15: 0.8, 16: 0.85, 17: 0.9, 18: 0.95, 19: 1.0}
回答が入力numpy配列のメンバーである必要がある場合:
単にnumpyのパーセンタイル関数がデフォルトで出力を入力ベクトルの2つの隣接するエントリの線形加重平均として計算することを追加するだけです。場合によっては、返されたパーセンタイルをベクトルの実際の要素にしたい場合があります。この場合、v1.9.0以降では、「補間」オプションを「低い」、「高い」、または「最も近い」のいずれかで使用できます。
import numpy as np
x=np.random.uniform(10,size=(1000))-5.0
np.percentile(x,70) # 70th percentile
2.075966046220879
np.percentile(x,70,interpolation="nearest")
2.0729677997904314
後者はベクトルの実際のエントリですが、前者はパーセンタイルに隣接する2つのベクトルエントリの線形補間です。
1次元のnumpyシーケンスまたは行列のパーセンタイルを計算する便利な方法は、numpy.percentile < https://docs.scipy.org/doc/numpy/reference/generated/numpy.percentile.html > を使用することです。例:
import numpy as np
a = np.array([0,1,2,3,4,5,6,7,8,9,10])
p50 = np.percentile(a, 50) # return 50th percentile, e.g median.
p90 = np.percentile(a, 90) # return 90th percentile.
print('median = ',p50,' and p90 = ',p90) # median = 5.0 and p90 = 9.0
ただし、データにNaN値がある場合、上記の関数は役に立ちません。その場合に使用することが推奨される関数は、numpy.nanpercentile < https://docs.scipy.org/doc/numpy/reference/generated/numpy.nanpercentile.html >関数です。
import numpy as np
a_NaN = np.array([0.,1.,2.,3.,4.,5.,6.,7.,8.,9.,10.])
a_NaN[0] = np.nan
print('a_NaN',a_NaN)
p50 = np.nanpercentile(a_NaN, 50) # return 50th percentile, e.g median.
p90 = np.nanpercentile(a_NaN, 90) # return 90th percentile.
print('median = ',p50,' and p90 = ',p90) # median = 5.5 and p90 = 9.1
上記の2つのオプションでは、補間モードを選択できます。理解を深めるために、以下の例に従ってください。
import numpy as np
b = np.array([1,2,3,4,5,6,7,8,9,10])
print('percentiles using default interpolation')
p10 = np.percentile(b, 10) # return 10th percentile.
p50 = np.percentile(b, 50) # return 50th percentile, e.g median.
p90 = np.percentile(b, 90) # return 90th percentile.
print('p10 = ',p10,', median = ',p50,' and p90 = ',p90)
#p10 = 1.9 , median = 5.5 and p90 = 9.1
print('percentiles using interpolation = ', "linear")
p10 = np.percentile(b, 10,interpolation='linear') # return 10th percentile.
p50 = np.percentile(b, 50,interpolation='linear') # return 50th percentile, e.g median.
p90 = np.percentile(b, 90,interpolation='linear') # return 90th percentile.
print('p10 = ',p10,', median = ',p50,' and p90 = ',p90)
#p10 = 1.9 , median = 5.5 and p90 = 9.1
print('percentiles using interpolation = ', "lower")
p10 = np.percentile(b, 10,interpolation='lower') # return 10th percentile.
p50 = np.percentile(b, 50,interpolation='lower') # return 50th percentile, e.g median.
p90 = np.percentile(b, 90,interpolation='lower') # return 90th percentile.
print('p10 = ',p10,', median = ',p50,' and p90 = ',p90)
#p10 = 1 , median = 5 and p90 = 9
print('percentiles using interpolation = ', "higher")
p10 = np.percentile(b, 10,interpolation='higher') # return 10th percentile.
p50 = np.percentile(b, 50,interpolation='higher') # return 50th percentile, e.g median.
p90 = np.percentile(b, 90,interpolation='higher') # return 90th percentile.
print('p10 = ',p10,', median = ',p50,' and p90 = ',p90)
#p10 = 2 , median = 6 and p90 = 10
print('percentiles using interpolation = ', "midpoint")
p10 = np.percentile(b, 10,interpolation='midpoint') # return 10th percentile.
p50 = np.percentile(b, 50,interpolation='midpoint') # return 50th percentile, e.g median.
p90 = np.percentile(b, 90,interpolation='midpoint') # return 90th percentile.
print('p10 = ',p10,', median = ',p50,' and p90 = ',p90)
#p10 = 1.5 , median = 5.5 and p90 = 9.5
print('percentiles using interpolation = ', "nearest")
p10 = np.percentile(b, 10,interpolation='nearest') # return 10th percentile.
p50 = np.percentile(b, 50,interpolation='nearest') # return 50th percentile, e.g median.
p90 = np.percentile(b, 90,interpolation='nearest') # return 90th percentile.
print('p10 = ',p10,', median = ',p50,' and p90 = ',p90)
#p10 = 2 , median = 5 and p90 = 9
入力配列が整数値のみで構成されている場合、整数としてのパーセンタイルの回答に興味があるかもしれません。その場合は、「低い」、「高い」、「最も近い」などの補間モードを選択します。