python / numpy를 사용하여 백분위 수를 어떻게 계산합니까?


214

시퀀스 또는 1 차원 numpy 배열의 백분위 수를 계산하는 편리한 방법이 있습니까?

Excel의 백분위 수 함수와 비슷한 것을 찾고 있습니다.

NumPy의 통계 참조를 보았는데 이것을 찾을 수 없었습니다. 내가 찾을 수있는 것은 중앙값 (50 백분위 수)이지만 더 구체적인 것은 아닙니다.


빈도로부터 백분위 수 계산에 관한 관련 질문 : stackoverflow.com/questions/25070086/…
newtover

답변:


282

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에 통합되지 않을 것이라고 믿게한다 .


2
감사합니다! 그것이 숨겨져있는 곳입니다. 나는 scipy를 알고 있었지만 백분위 수와 같은 간단한 것들이 숫자로 만들어 질 것이라고 생각합니다.
Uri

16
이제 백분위 수 함수는 numpy에 존재합니다. docs.scipy.org/doc/numpy/reference/generated/…
Anaphory

1
키로 값 열의 각 그룹의 10 번째 백분위 수를 계산하려면 집계 함수로도 사용할 수 있습니다.df.groupby('key')[['value']].agg(lambda g: np.percentile(g, 10))
patricksurry

1
SciPy가 NumPy와 1.9 이상에서 np.percentile 사용하도록 권장하는 참고
timdiels

73

그건 그렇고, 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/ }}}

54
위 레시피의 저자입니다. ASPN의 주석가는 원래 코드에 버그가 있다고 지적했습니다. 공식은 d0 = key (N [int (f)]) * (ck) 여야합니다. d1 = 키 (N [int (c)]) * (kf). ASPN에서 수정되었습니다.
Wai Yip Tung

1
percentile무엇을 사용해야하는지 어떻게 알 수 N있습니까? 함수 호출에 지정되지 않았습니다.
Richard

14
코드를 읽지 않은 사람들을 위해 코드를 사용하기 전에 N을 정렬해야합니다.
kevin

람다 식에 혼란스러워합니다. 그것은 무엇을하고 어떻게합니까? 나는 람다 표현이 무엇인지 알고 있으므로 람다가 무엇인지 묻지 않습니다. 이 특정 람다 식의 기능은 무엇이며 단계별로 어떻게 수행합니까? 감사!
dsanchez

람다 함수를 사용하면 N백분위 수를 계산하기 전에 데이터를 변환 할 수 있습니다 . 실제로 튜플 목록이 있고 튜플 N = [(1, 2), (3, 1), ..., (5, 1)]첫 번째 요소의 백분위 수를 구하고 싶다고 가정 하십시오 key=lambda x: x[0]. 백분위 수를 계산하기 전에 목록 요소에 (순서 변경) 변환을 적용 할 수도 있습니다.
Elias Strehle

26
import numpy as np
a = [154, 400, 1124, 82, 94, 108]
print np.percentile(a,95) # gives the 95th percentile

19

다음은 백분위 수를 계산하기 위해 파이썬 만 사용하여 numpy없이 수행하는 방법입니다.

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)

2
예,리스트를 정렬해야합니다 : mylist = sorted (...)
Ashkan

12

필자가 본 백분위 수의 정의는 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]

감사합니다, 또한 백분위 수 / 중앙값이 보간이 아닌 세트의 실제 값을 초래할 것으로 예상합니다.
hansaplast

1
안녕하세요 @mpounsett. 위 코드에 감사드립니다. 백분위 수가 항상 정수 값을 반환하는 이유는 무엇입니까? 백분위 수 함수는 값 목록의 N 번째 백분위 수를 반환해야하며 이는 부동 소수 일 수도 있습니다. 예를 들어, 엑셀 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).
marco

1
첫 문장에서 설명합니다. 백분위 수에 대한보다 일반적인 정의는 계열에있는 값의 P %를 찾을 수있는 계열 이하의 숫자라는 것입니다. 이것이 목록에있는 항목의 색인 번호이므로 부동 소수점 일 수 없습니다.
mpounsett

0 번째 백분위 수에는 작동하지 않습니다. 최대 값을 반환합니다. 빠른 수정은 포장하는 것 n = int(...)A의 max(int(...), 1)기능
ijustlovemath

명확히하기 위해 두 번째 예에서 의미합니까? 최대 값이 아닌 0을 얻습니다. 버그는 실제로 else 절에 있습니다. 의도 한 값이 아닌 색인 번호를 인쇄했습니다. max () 호출에서 'n'의 할당을 래핑하면 문제가 해결되지만 두 번째 값은 1이 아닌 2가되기를 원할 것입니다. 그런 다음 전체 if / else 구조를 제거하고 N의 결과를 인쇄 할 수 있습니다 [n-2]. 첫 번째 예제에서는 0 번째 백분위 수가 제대로 작동하여 각각 '1'과 '15'를 반환합니다.
mpounsett

8

시작 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주어진 분포 distn - 1대해 nQuantile 간격을 분리하는 컷 포인트 목록을 반환 합니다 ( 동일한 확률 distn연속 간격으로 나눔).

statistics.quantiles (dist, *, n = 4, method = 'exclusive')

여기서 n우리의 경우 ( percentiles)는 100입니다.


6

scipy.stats 모듈을 확인하십시오.

 scipy.stats.scoreatpercentile

2

계열의 백분위 수를 계산하려면 다음을 실행하십시오.

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}

1

입력 numpy 배열의 멤버가되는 답변이 필요한 경우 :

기본적으로 numpy의 백분위 수 함수는 기본적으로 출력을 입력 벡터의 두 인접 항목의 선형 가중 평균으로 계산합니다. 어떤 경우에는 반환 백분위 수가 벡터의 실제 요소가되기를 원할 수 있습니다.이 경우 v1.9.0부터 "interpolation"옵션을 "lower", "higher"또는 "nearest"와 함께 사용할 수 있습니다.

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

후자는 벡터의 실제 엔트리이고, 후자는 백분위 수를 경계로하는 두 개의 벡터 엔트리의 선형 보간입니다.


0

시리즈 : 설명 함수 사용

sales 및 id 열에 df가 있다고 가정하십시오. 매출의 백분위 수를 계산하려면 다음과 같이 작동합니다.

df['sales'].describe(percentiles = [0.0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1])

0.0: .0: minimum
1: maximum 
0.1 : 10th percentile and so on

0

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

위에 제시된 두 가지 옵션에서 여전히 보간 모드를 선택할 수 있습니다. 이해하기 쉽도록 아래 예를 따르십시오.

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

입력 배열이 정수 값으로 만 구성된 경우 백분위 수 대답을 정수로 사용할 수 있습니다. 그렇다면 '낮게', '높게'또는 '가장 가까운'과 같은 보간 모드를 선택하십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.