Yüzdelikleri python / numpy ile nasıl hesaplayabilirim?


214

Bir dizi veya tek boyutlu numpy dizisi için yüzdelik değerleri hesaplamanın uygun bir yolu var mı?

Excel'in yüzdelik işlevine benzer bir şey arıyorum.

NumPy'nin istatistik referansına baktım ve bulamadım. Tüm bulabildiğim medyan (50. persentil), ama daha spesifik bir şey değil.


Frekanslardan yüzdelik değerlerin hesaplanması ile ilgili bir soru: stackoverflow.com/questions/25070086/…
newtover

Yanıtlar:


282

SciPy İstatistikleri paketiyle ilgileniyor olabilirsiniz . Bu sahiptir yüzdelik fonksiyonunu Peşinde ve diğer birçok istatistiki güzellikler konum.

percentile() kullanılabilir içinde numpyde.

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

Bu bilet beni yakın zamanda percentile()numpy'ye entegre olmayacaklarına inandırıyor .


2
Teşekkür ederim! Yani saklandığı yer burası. Scipy'nin farkındaydım ama sanırım persentiller gibi basit şeylerin numpy haline getirileceğini düşündüm.
Uri

16
Şimdiye kadar, numpy'de
Anaphory

1
Bir toplama işlevi olarak da kullanabilirsiniz, örneğin bir değer sütununun her bir grubunun onuncu yüzdelik df.groupby('key')[['value']].agg(lambda g: np.percentile(g, 10))
dilimini

1
SciPy'nin NumPy 1.9 ve üstü için np.centcentile kullanılmasını önerdiğini unutmayın
timdiels

73

Bu arada, bir kişinin scipy'ye bağımlı olmak istememesi durumunda , yüzdelik fonksiyonun saf bir Python uygulaması vardır . İşlev aşağıda kopyalanmıştır:

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

54
Yukarıdaki tarifin yazarıyım. ASPN'deki bir yorumcu orijinal kodun bir hata olduğunu belirtti. Formül d0 = anahtar (N [int (f)]) * (ck) olmalıdır; d1 = anahtar (N [int (c)]) * (kf). ASPN'de düzeltildi.
Wai Yip Tung

1
Ne percentileiçin kullanılacağını nasıl bilebilir N? İşlev çağrısında belirtilmemiş.
Richard

14
kodu okumayanlar için, kullanmadan önce, N sıralanmalıdır
kevin

Lambda ifadesiyle kafam karıştı. Ne işe yarar ve nasıl yapar? Lambda ifadesinin ne olduğunu biliyorum, bu yüzden lambda'nın ne olduğunu sormuyorum. Bu belirli lambda ifadesinin ne yaptığını ve adım adım nasıl yaptığını soruyorum. Teşekkürler!
dsanchez

Lambda işlevi, Nbir yüzdelik değeri hesaplamadan önce verileri dönüştürmenizi sağlar . Diyelim ki aslında bir tuples listeniz var ve tuple'lerin ilk elemanının N = [(1, 2), (3, 1), ..., (5, 1)]yüzdelik dilimini almak istiyorsunuz , o zaman seçin . Bir yüzdelik değeri hesaplamadan önce liste öğelerine bazı (sıra değiştiren) dönüşümler de uygulayabilirsiniz. key=lambda x: x[0]
Elias Strehle

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

19

Yüzdelik değeri hesaplamak için sadece python kullanarak, numpy olmadan nasıl yapacağınız aşağıda açıklanmıştır.

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)

2
Evet, listeyi daha önce sıralamanız gerekiyor: mylist = sorted (...)
Ashkan

12

Gördüğüm persentil tanımı genellikle sonuç olarak verilen listeden değerlerin yüzde P'sinin bulunduğu değeri bekler ... bu da sonucun set elemanları arasında bir enterpolasyon değil setten olması gerektiği anlamına gelir. Bunu elde etmek için daha basit bir işlev kullanabilirsiniz.

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

Değeri, yüzde değerlerin bulunduğu P veya altında verilen listeden almak isterseniz, bu basit değişikliği kullanın:

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

Veya @ijustlovemath tarafından önerilen sadeleştirme ile:

def percentile(N, P):
    n = max(int(round(P * len(N) + 0.5)), 2)
    return N[n-2]

teşekkürler, ben de persentil / medyan enterpolasyonlar değil, setlerden gerçek değerlerin sonuçlanmasını bekliyoruz
hansaplast

1
Merhaba @mpounsett. Üst kod için teşekkürler. Yüzdelik dilim neden daima tamsayı değerleri döndürüyor? Yüzdelik işlevi, bir değer listesinin N'inci yüzdelik dilimini döndürmelidir ve bu bir kayan sayı da olabilir. Örneğin, Excel PERCENTILEfonksiyonu üst örnekler için aşağıdaki yüzdelik döndürür: 3.7 = percentile(A, P=0.3), 0.82 = percentile(A, P=0.8), 20 = percentile(B, P=0.3), 42 = percentile(B, P=0.8).
marco

1
İlk cümlede açıklanmıştır. Yüzdelik dilimin daha yaygın tanımı, dizideki değerlerin yüzde P'sinin bulunduğu bir dizideki sayı olmasıdır. Bu listedeki bir öğenin dizin numarası olduğundan, kayan nokta olamaz.
mpounsett

Bu 0'ıncı yüzdelik dilim için geçerli değildir. Maksimum değeri döndürür. Hızlı bir düzeltme n = int(...)bir max(int(...), 1)fonksiyonda sarmak olacaktır
ijustlovemath

Açıklığa kavuşturmak için, ikinci örnekte mi demek istiyorsun? Maksimum değer yerine 0 alıyorum. Hata aslında başka bir cümledir .. Ben amaçlanan değeri yerine dizin numarasını yazdırdı. Bir max () çağrısında 'n' atamasının düzeltilmesi de bunu düzeltir, ancak ikinci değerin 1 değil 2 olmasını istersiniz. İf / else yapısının tamamını ortadan kaldırabilir ve yalnızca N sonucunu yazdırabilirsiniz. [n-2]. Yüzde yüzdelik değer ilk örnekte düzgün çalışarak sırasıyla '1' ve '15' döndürür.
mpounsett

8

Başlangıçta Python 3.8, standart kütüphane modülün bir quantilesparçası olarak işlevle birlikte gelir statistics:

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

quantilesBelirli bir dağılım için döner distbir listesi n - 1ayırma kesim noktaları n(bölünmesini quantile aralıkları distiçine neşit olasılıkla devamlı aralıklarla):

statistics.quantiles (dist, *, n = 4, yöntem = 'özel')

nerede n, bizim durumumuzda ( percentiles) 100.



2

Bir serinin yüzdelik değerini hesaplamak için şunu çalıştırın:

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

Örneğin:

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}

1

Girdi numpy dizisinin üyesi olmak için cevaba ihtiyacınız olması durumunda:

Sadece varsayılan olarak numpy içindeki yüzdelik işlevinin çıktıyı girdi vektöründeki iki komşu girişin doğrusal ağırlıklı ortalaması olarak hesapladığını eklemek için. Bazı durumlarda insanlar döndürülen yüzdelik değerin vektörün gerçek bir öğesi olmasını isteyebilir, bu durumda v1.9.0'dan itibaren "enterpolasyon" seçeneğini "düşük", "daha yüksek" veya "en yakın" seçenekleriyle kullanabilirsiniz.

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

İkincisi, vektördeki gerçek bir girişken, birincisi, yüzdelik dilimi sınırlayan iki vektör girişinin doğrusal enterpolasyonudur.


0

bir dizi için: kullanılan açıklama işlevleri

Aşağıdaki sütun satış ve kimliği ile df var varsayalım. satış için yüzdelikleri hesaplamak istiyorsanız, o zaman böyle çalışır,

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

Tek boyutlu bir numpy dizisi veya matrisi için persentilleri hesaplamanın uygun bir yolu numpy.percentile < https://docs.scipy.org/doc/numpy/reference/generated/numpy.percentile.html > kullanmaktır. Misal:

import numpy as np

a = np.array([0,1,2,3,4,5,6,7,8,9,10])
p50 = np.percentile(a, 50) # return 50th percentile, e.g median.
p90 = np.percentile(a, 90) # return 90th percentile.
print('median = ',p50,' and p90 = ',p90) # median =  5.0  and p90 =  9.0

Ancak, verilerinizde herhangi bir NaN değeri varsa, yukarıdaki işlev yararlı olmayacaktır. Bu durumda kullanılması önerilen işlev numpy.nanpercentile < https://docs.scipy.org/doc/numpy/reference/generated/numpy.nanpercentile.html > işlevidir:

import numpy as np

a_NaN = np.array([0.,1.,2.,3.,4.,5.,6.,7.,8.,9.,10.])
a_NaN[0] = np.nan
print('a_NaN',a_NaN)
p50 = np.nanpercentile(a_NaN, 50) # return 50th percentile, e.g median.
p90 = np.nanpercentile(a_NaN, 90) # return 90th percentile.
print('median = ',p50,' and p90 = ',p90) # median =  5.5  and p90 =  9.1

Yukarıda sunulan iki seçenekte yine de enterpolasyon modunu seçebilirsiniz. Daha kolay anlaşılması için aşağıdaki örnekleri izleyin.

import numpy as np

b = np.array([1,2,3,4,5,6,7,8,9,10])
print('percentiles using default interpolation')
p10 = np.percentile(b, 10) # return 10th percentile.
p50 = np.percentile(b, 50) # return 50th percentile, e.g median.
p90 = np.percentile(b, 90) # return 90th percentile.
print('p10 = ',p10,', median = ',p50,' and p90 = ',p90)
#p10 =  1.9 , median =  5.5  and p90 =  9.1

print('percentiles using interpolation = ', "linear")
p10 = np.percentile(b, 10,interpolation='linear') # return 10th percentile.
p50 = np.percentile(b, 50,interpolation='linear') # return 50th percentile, e.g median.
p90 = np.percentile(b, 90,interpolation='linear') # return 90th percentile.
print('p10 = ',p10,', median = ',p50,' and p90 = ',p90)
#p10 =  1.9 , median =  5.5  and p90 =  9.1

print('percentiles using interpolation = ', "lower")
p10 = np.percentile(b, 10,interpolation='lower') # return 10th percentile.
p50 = np.percentile(b, 50,interpolation='lower') # return 50th percentile, e.g median.
p90 = np.percentile(b, 90,interpolation='lower') # return 90th percentile.
print('p10 = ',p10,', median = ',p50,' and p90 = ',p90)
#p10 =  1 , median =  5  and p90 =  9

print('percentiles using interpolation = ', "higher")
p10 = np.percentile(b, 10,interpolation='higher') # return 10th percentile.
p50 = np.percentile(b, 50,interpolation='higher') # return 50th percentile, e.g median.
p90 = np.percentile(b, 90,interpolation='higher') # return 90th percentile.
print('p10 = ',p10,', median = ',p50,' and p90 = ',p90)
#p10 =  2 , median =  6  and p90 =  10

print('percentiles using interpolation = ', "midpoint")
p10 = np.percentile(b, 10,interpolation='midpoint') # return 10th percentile.
p50 = np.percentile(b, 50,interpolation='midpoint') # return 50th percentile, e.g median.
p90 = np.percentile(b, 90,interpolation='midpoint') # return 90th percentile.
print('p10 = ',p10,', median = ',p50,' and p90 = ',p90)
#p10 =  1.5 , median =  5.5  and p90 =  9.5

print('percentiles using interpolation = ', "nearest")
p10 = np.percentile(b, 10,interpolation='nearest') # return 10th percentile.
p50 = np.percentile(b, 50,interpolation='nearest') # return 50th percentile, e.g median.
p90 = np.percentile(b, 90,interpolation='nearest') # return 90th percentile.
print('p10 = ',p10,', median = ',p50,' and p90 = ',p90)
#p10 =  2 , median =  5  and p90 =  9

Giriş diziniz yalnızca tamsayı değerlerden oluşuyorsa, yüzde değeri yanıtı bir tamsayı olarak ilgilenebilirsiniz. Öyleyse, 'alt', 'daha yüksek' veya 'en yakın' gibi enterpolasyon modunu seçin.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.