Comment calculer les percentiles avec Python / numpy?

Existe-t-il un moyen pratique de calculer des percentiles pour une séquence ou un tableau numpy unidimensionnel?

Je cherche quelque chose de similaire à la fonction percentile D'Excel.

J'ai regardé dans la référence statistique de NumPy, et je n'ai pas pu trouver cela. Tout ce que j'ai pu trouver est la médiane (50e percentile), mais pas quelque chose de plus spécifique.

152
demandé sur Uri 2010-03-03 23:21:13

8 réponses

Vous pourriez être intéressé par le paquetscipy Stats . Il a la fonction percentile Vous êtes après et beaucoup d'autres goodies statistiques.

percentile() est disponible dans numpy trop.

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

Ce ticket m'amène à croire qu'ils ne vont pas intégrer percentile() dans numpy de sitôt.

204
répondu Jon W 2014-09-06 19:09:59

En passant, il y a une implémentation pure-Python de la fonction percentile , au cas où on ne voudrait pas dépendre de scipy. La fonction est copiée ci-dessous:

## {{{ 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/ }}}
55
répondu Boris Gorelik 2011-09-15 06:37:56
import numpy as np
a = [154, 400, 1124, 82, 94, 108]
print np.percentile(a,95) # gives the 95th percentile
23
répondu richie 2013-06-12 07:45:24

La définition de percentile que je vois habituellement attend en conséquence la valeur de la liste fournie ci-dessous laquelle P pour cent des valeurs sont trouvées... ce qui signifie que le résultat doit être de l'ensemble, pas une interpolation entre les éléments. Pour obtenir cela, vous pouvez utiliser une fonction plus simple.

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

Si vous préférez obtenir la valeur de la liste fournie à ou en dessous de laquelle P pour cent des valeurs sont trouvées, utilisez cette modification simple:

def percentile(N, P):
    n = int(round(P * len(N) + 0.5))
    if n > 1:
        return N[n-2]
    else:
        return N[0]

Ou avec la simplification suggérée par @ijustlovemath:

def percentile(N, P):
    n = max(int(round(P * len(N) + 0.5)), 2)
    return N[n-2]
8
répondu mpounsett 2017-02-08 03:39:05

Vérifiez scipy.statistiques module:

 scipy.stats.scoreatpercentile
7
répondu Evert 2014-10-21 01:19:35

Voici comment le faire sans numpy, en utilisant uniquement python pour calculer le percentile.

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)
6
répondu Ashkan 2014-11-19 20:44:41

Pour calculer le percentile d'une série, exécutez:

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))

Par exemple:

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}
2
répondu Roei Bahumi 2017-08-02 12:54:16

Si vous avez besoin de la réponse pour être membre du tableau numpy d'Entrée:

Juste pour ajouter que la fonction percentile dans numpy calcule par défaut la sortie comme une moyenne pondérée linéaire des deux entrées voisines dans le vecteur d'entrée. Dans certains cas, les gens peuvent vouloir que le centile retourné soit un élément réel du vecteur, dans ce cas, à partir de V1.9.0, Vous pouvez utiliser l'option" interpolation", avec" lower"," higher "ou"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

Le ce dernier est une entrée réelle dans le vecteur, tandis que le premier est une interpolation linéaire de deux entrées vectorielles qui bordent le percentile

0
répondu Adrian Tompkins 2018-03-22 12:55:45