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

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.