web-dev-qa-db-fra.com

Comment calculer les centiles avec python / numpy?

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.

183
Uri

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.

240
Jon W

À 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/ }}}
65
Boris Gorelik
import numpy as np
a = [154, 400, 1124, 82, 94, 108]
print np.percentile(a,95) # gives the 95th percentile
25
richie

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

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]
10
mpounsett

vérifiez le module scipy.stats:

 scipy.stats.scoreatpercentile
7
Evert

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

n, dans notre cas (percentiles), est 100.

2
Xavier Guihot

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}
2
Roei Bahumi

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

1
Adrian Tompkins

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
0
ashwini