Existe-t-il un moyen pratique de calculer des centiles pour une séquence ou un tableau numpy à une dimension?
Je recherche quelque chose de similaire à la fonction de centile d'Excel.
J'ai regardé dans la référence des statistiques de NumPy et je n'ai pas pu le trouver. Tout ce que j'ai pu trouver, c'est la médiane (50e centile), mais pas quelque chose de plus spécifique.
Vous pourriez être intéressé par le package SciPy Stats . Il a la fonction de centile que vous recherchez et de nombreux autres avantages statistiques.
percentile()
est disponible dans numpy
également.
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 n'intégreront pas percentile()
dans numpy dans un avenir proche.
À propos, il y a ne implémentation en Python pure de la fonction de centile , 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/ }}}
import numpy as np
a = [154, 400, 1124, 82, 94, 108]
print np.percentile(a,95) # gives the 95th percentile
Voici comment le faire sans numpy, en utilisant uniquement python pour calculer le centile.
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)
La définition du percentile que je vois habituellement attend en conséquence la valeur de la liste fournie en dessous de laquelle P pour cent des valeurs sont trouvées ... ce qui signifie que le résultat doit provenir de l'ensemble, et non d'une interpolation entre les éléments de l'ensemble. Pour 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% de valeurs sont trouvées, utilisez cette simple modification:
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]
vérifiez le module scipy.stats:
scipy.stats.scoreatpercentile
À partir de Python 3.8
, la bibliothèque standard est livrée avec la fonction quantiles
dans le cadre de statistics
module:
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
renvoie pour une distribution donnée dist
une liste de n - 1
points coupants séparant les intervalles quantiles n
(division de dist
en n
intervalles continus égaux probabilité):
statistiques.quantiles (dist, *, n = 4, méthode = 'exclusif')
où n
, dans notre cas (percentiles
), est 100
.
Pour calculer le centile 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}
Si vous avez besoin que la réponse soit membre du tableau numpy en entrée:
Ajoutons simplement que la fonction de centile dans numpy par défaut calcule la sortie sous forme de moyenne pondérée linéaire des deux entrées voisines du vecteur d’entrée. Dans certains cas, les utilisateurs peuvent souhaiter que le centile renvoyé soit un élément réel du vecteur. Dans ce cas, à partir de la version 1.9.0, vous pouvez utiliser l'option "interpolation", avec les options "inférieur", "supérieur" ou "le plus proche".
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 dernier est une entrée réelle dans le vecteur, tandis que le premier est une interpolation linéaire de deux entrées de vecteur qui bordent le centile
pour une série: utilisé décrire des fonctions
supposons que vous ayez df avec les colonnes suivantes sales et id. vous voulez calculer les centiles pour les ventes alors ça marche comme ça,
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