Как рассчитать процентили с помощью python / numpy?

есть ли удобный способ вычисления процентилей для последовательности или одномерного массива numpy?

Я ищу что-то похожее на функцию Excel процентиля.

Я посмотрел в справочнике статистики NumPy и не смог найти это. Все, что я смог найти-это медиана (50-й процентиль), а не что-то более конкретное.

8 ответов


вас может заинтересовать Статистика SciPy пакета. Он имеет функция процентиль вы после и многих других статистических лакомств.

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 в ближайшее время.


кстати, есть реализация Pure-Python функции процентиля, в случае, если вы не хотите зависеть от scipy. Функция копируется ниже:

## {{{ 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/ }}}

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

определение процентиля, которое я обычно вижу, ожидает в результате значение из предоставленного списка, ниже которого находятся 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]

проверьте наличие scipy.Модуль статистики:

 scipy.stats.scoreatpercentile

вот как это сделать без 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)

чтобы вычислить процентиль ряда, выполните:

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 по умолчанию вычисляет выход как линейное средневзвешенное значение двух соседних записей во входном векторе. В некоторых случаях люди могут хотеть, чтобы возвращаемый процентиль был фактическим элементом вектора, в этом случае из 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

последний является фактической записью в векторе, в то время как первый является линейной интерполяцией двух векторных записей, граничащих с процентилем