python - p95 - pandas percentile
¿Cómo calculo los percentiles con python/numpy? (8)
¿Hay una manera conveniente de calcular percentiles para una secuencia o matriz numpy unidimensional?
Estoy buscando algo similar a la función percentil de Excel.
Busqué en la referencia de estadísticas de NumPy, y no pude encontrar esto. Todo lo que pude encontrar es la mediana (percentil 50), pero no algo más específico.
Aquí le mostramos cómo hacerlo sin numpy, usando solo python para calcular el percentil.
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 definición de percentil que suelo ver espera como resultado el valor de la lista suministrada por debajo del cual se encuentran P por ciento de los valores ... lo que significa que el resultado debe ser del conjunto, no una interpolación entre los elementos del conjunto. Para obtener eso, puedes usar una función más 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 prefiere obtener el valor de la lista suministrada en o por debajo del cual se encuentran P por ciento de los valores, entonces use esta simple modificación:
def percentile(N, P):
n = int(round(P * len(N) + 0.5))
if n > 1:
return N[n-2]
else:
return N[0]
O con la simplificación sugerida por @ijustlovemath:
def percentile(N, P):
n = max(int(round(P * len(N) + 0.5)), 2)
return N[n-2]
Para calcular el percentil de una serie, ejecuta:
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))
Por ejemplo:
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}
Por cierto, hay una implementación de Python pura de la función percentil , en caso de que uno no quiera depender de scipy. La función se copia a continuación:
## {{{ 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/ }}}
Puede que le interese el paquete SciPy Stats . Tiene la función percentil que buscas y muchos otros objetos estadísticos.
percentile()
está disponible en 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
Este boleto me lleva a creer que no integrarán el percentile()
en numpy pronto.
compruebe el módulo scipy.stats:
scipy.stats.scoreatpercentile
En caso de que necesite la respuesta para ser un miembro de la matriz numpy de entrada:
Solo para agregar que la función percentil en numpy de forma predeterminada calcula la salida como un promedio ponderado lineal de las dos entradas contiguas en el vector de entrada. En algunos casos, las personas pueden desear que el percentil devuelto sea un elemento real del vector; en este caso, desde la v1.9.0 en adelante puede usar la opción "interpolación", ya sea con "inferior", "superior" o "más cercano".
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
Esta última es una entrada real en el vector, mientras que la primera es una interpolación lineal de dos entradas de vectores que bordean el percentil
import numpy as np
a = [154, 400, 1124, 82, 94, 108]
print np.percentile(a,95) # gives the 95th percentile