Numpy: Merestrukturisasi metode persentil

Dibuat pada 12 Mar 2018  ·  53Komentar  ·  Sumber: numpy/numpy

Seperti yang dicontohkan di halaman Wikipedia: https://en.wikipedia.org/wiki/Percentile#The_nearest -rank_method

00 - Bug 01 - Enhancement high

Semua 53 komentar

Saya pikir ini sudah ada? Menggunakan contoh wikipedia:

>>> np.percentile(15, 20, 35, 40, 50], [5, 30, 40, 50, 100], interpolation='lower')
array([15, 20, 20, 35, 50])

Itu tidak. Lihat contoh 2 di halaman wikipedia:

>>> np.percentile([3, 6, 7, 8, 8, 10, 13, 15, 16, 20], [25,50,75,100], interpolation='lower')
array([ 7,  8, 13, 20])

Kapan seharusnya [7,8,15,20]

Hal serupa juga gagal pada contoh ketiga

Suara terdekat sangat mirip dengan "terdekat"? Meskipun selalu ada poin lain tentang bagaimana tepatnya batasan itu bekerja.
EDIT: Yaitu, di mana tepatnya 0 dan 100 dianggap, di titik data atau sebelum titik data? (itu IIRC, toh ada banyak kerumitan yang mengganggu di sini)

tidak ingin membacanya, saya pikir perbedaannya mungkin pada parameter C lebih jauh, jadi jika seseorang yang mengetahui ini ingin menambahkan ini ....

Terus terang, saya pikir menambahkan parameter C kemungkinan besar akan sangat bagus. Tetapi sebagian besar dokumentasi yang lebih baik akan menyenangkan, dan seseorang yang benar -

Saya tidak tahu apakah ini ada hubungannya dengan parameter C, meskipun saya setuju bahwa opsi untuk memilihnya bisa diinginkan.

Saya telah menemukan utas lain yang secara tidak sengaja mengangkat masalah ini (Desember 2016). Tampaknya algoritme yang saya cari (dan yang wikipedia sebut peringkat terdekat) disebutkan dalam makalah yang sering dikutip ini

Berikut adalah tampilannya terhadap opsi lain yang disediakan oleh numpy yang secara intuitif tampak menghitung hal yang serupa (yaitu, 'lebih rendah', 'terdekat'):

percentiles

Bagi saya ini terlihat persis seperti parameter C pada pandangan pertama, kurva terdekat lebih melebar daripada kurva H&F, yang diharapkan karena numpy menggunakan 1 dan ternyata H&F menggunakan 0.

Jika Anda ingin bukti. Ulangi semuanya dengan nilai yang sama diulang 1000 kali, tebakan saya adalah mereka akan bertemu.
EDIT: Atau mungkin tidak, tidak memiliki kesabaran atau waktu untuk benar-benar memikirkannya. Tapi saya masih berpikir itu adalah parameter C yang disebutkan wikipedia, jadi tolong buktikan saya salah :)

Grafik seperti itu akan menjadi tambahan yang bagus untuk dokumen persentil

edit: lebih disukai yang menunjukkan keterbukaan / tertutupnya diskontinuitas

Catatan untuk pembaca: Agar utas ini tetap dapat dikelola, saya telah menandai semua diskusi di bawah ini tentang menambahkan grafik ini ke dokumen sebagai "terselesaikan". Grafik sekarang ada di bagian bawah https://numpy.org/devdocs/reference/generated/numpy.percentile.html.

@ eric-wieser Saya tidak keberatan membuat grafik itu. Saya akan kembali dengan sesuatu hari ini, haruskah saya mempostingnya di sini?

@seberg Saya akan jujur ​​di sini, saya tidak tahu bagaimana interpolasi dihitung berdasarkan parameter C. Apa yang membuat saya berpikir bahwa itu tidak terkait adalah bahwa C-parameter hanya dibahas di bagian interpolasi linier (Wikipedia), dan baik makalah Wikipedia dan Hyndmand & Fan membahas algoritma yang saya minta di bagian terpisah dari yang interpolasi.

Saya tidak tahu apakah ada parameter interpolasi yang selalu memberikan hasil yang sama dengan algoritma yang saya minati.

Kalaupun ada, haruskah ini cara yang biasa digunakan untuk mencapainya? Mengubah parameter 'aneh' untuk mendapatkan definisi persentil yang paling umum tampaknya bukan cara terbaik untuk mengimplementasikannya.

@ ricardoV94 , mungkin, tetapi Anda tidak bisa begitu saja mengubah default, tidak peduli seberapa buruknya. Kita bisa mengekspos sesuatu seperti method = "H&K" untuk mengganti kedua parameter sekaligus.

Parameter C adalah tempat Anda menentukan 0% dan 100% sehubungan dengan titik data (pada titik data atau tidak, dll.). Sebagai parameter C di wikipedia, ini mungkin hanya untuk interpolasi, tetapi masalah yang sama menyebabkan perbedaan di sini, saya yakin. C tentu saja meragukan, nama yang tepat mungkin sesuatu seperti range = 'min-max' atau range = 'extrapolated' atau mungkin sesuatu yang sama sekali berbeda. Seperti yang saya katakan, ulangi plot dengan banyak titik data (mungkin dengan noise kecil), dan saya pikir Anda akan melihatnya bertemu, karena definisi jangkauan menjadi kurang jelas.

@seberg Saya baik-baik saja dengan metode = "H&K" atau mungkin metode = "klasik". Interpolation = "none" juga bisa masuk akal.

Saya tidak yakin apa mekanisme untuk memasukkan gambar ke dalam dokumen, atau apakah ada preseden untuk melakukannya.

Saya tahu Anda dapat menjalankan kode matplotlib di dalam dokumen, seperti yang kami lakukan di tempat lain - yang juga memastikannya tetap tersinkronisasi dengan kenyataan.

Oke, saya akan memikirkan gambar kode terbaik dalam kasus itu.

Bagian yang paling bermasalah adalah penanda yang terbuka dan tertutup untuk diskontinuitas, karena matplotlib tidak memiliki fungsi bawaan untuk itu (afaik). Mengkodekannya secara keras tidak akan masuk akal dalam kasus itu.

Mungkin lewati itu untuk saat ini. Alangkah baiknya jika matplotlib memiliki beberapa dukungan otomatis untuk itu.

Mudah-mudahan ada yang punya saran yang lebih baik, yaitu tetap elegan mengenai diskontinuitas.

import matplotlib.pyplot as plt

a = [0,1,2,3]
p = np.arange(101)

plt.step(p, np.percentile(a, p, interpolation='linear'), label='linear')
plt.step(p, np.percentile(a, p, interpolation='higher'), label='higher', linestyle='--')
plt.step(p, np.percentile(a, p, interpolation='lower'), label='lower', linestyle='--')
plt.step(p, np.percentile(a, p, interpolation='nearest'), label='nearest', linestyle='-.',)
plt.step(p, np.percentile(a, p, interpolation='midpoint'), label='midpoint', linestyle='-.',)

plt.title('Interpolation methods for list: ' + str(a))
plt.xlabel('Percentile')
plt.ylabel('List item returned')
plt.yticks(a)
plt.legend()

Image

Saya pikir interpolation = 'linear' harus berupa garis biasa bukan berundak, tetapi sebaliknya terlihat bagus. Bisakah Anda membuat PR menambahkannya ke dokumen?

Faktanya, step umumnya menyebabkan artefak yang menyesatkan, jadi saya cenderung menghindarinya. linspace(0, 100, 60) akan menghasilkan koordinat antara yang lebih akurat juga

Saya tidak tahu bagaimana membuat PR.

Jangan ragu untuk melakukannya dengan akun Anda, menambahkan atau mendiskusikan perubahan yang disarankan.

Saya pikir Anda dapat mengubah C dengan sesuatu seperti ini (uji coba pada sesuatu). Panggil fungsi pada persentil Anda, lalu hubungkan ke versi numpy (yang menggunakan C = 1, yang merupakan no-op kecuali mengoreksi persentil yang terikat sekarang):

def scale_percentiles(p, num, C=0):
     """
     p : float
          percentiles to be used (within 0 and 100 inclusive)
     num : int
         number of data points.
     C : float
         parameter C, should be 0, 0.5 or 1. Numpy uses 1, matlab 0.5, H&K is 0.
     """
     p = np.asarray(p)
     fact = (num-1.+2*C)/(num-1)
     p *= fact
     p -= 0.5 * (fact-1) * 100
     p[p < 0] = 0
     p[p > 100] = 100
     return p

Dan voila, dengan "terdekat" Anda akan mendapatkan "H&F" Anda dan dengan linier Anda akan mendapatkan plot dari Wikipedia. (sambil menunggu bahwa saya melakukan sesuatu yang salah, tetapi saya cukup yakin saya melakukannya dengan benar).

Seperti yang saya katakan, perbedaannya adalah tempat Anda menempatkan poin data dari 0-100 (merata) sehubungan dengan poin terakhir. Untuk C = 1 Anda meletakkan min (data) ke persentil 0, dll. Saya tidak tahu tentang "apa yang lebih masuk akal", ini mungkin sedikit penting dari tampilan umum. Nama inklusif untuk 1 dan eksklusif untuk 0 agak masuk akal saya kira (ketika Anda memikirkan tentang kisaran total persentil, karena eksklusif kisaran yang mungkin berada di luar kisaran data). C = 1/2 juga eksklusif dalam pengertian itu.

Saya akan menambahkan parameter C, tetapi saya ingin seseorang membuat nama deskriptif jika memungkinkan. Saya juga tidak keberatan sesuatu seperti "metode" atau lebih untuk membuat default terbaik jelas (kombinasi interpolasi + C). Atau, Anda pada dasarnya kami memutuskan bahwa sebagian besar kombinasi tidak pernah digunakan dan tidak berguna, baiklah ....

Pada akhirnya masalah saya adalah: Saya ingin seorang ahli statistik memberi tahu saya metode mana yang memiliki konsensus (R memiliki beberapa hal, tetapi terakhir kali seseorang datang ke sini, itu hanya salinan R doc atau serupa tanpa mengaturnya ke dalam konteks numpy di semua, tentu saja, itu tidak berguna untuk khalayak umum, mengutip makalah akan lebih membantu).

Saya tidak ingin membaca makalah H&F itu (sejujurnya juga tidak terlalu apik untuk dibaca), tetapi saya rasa Anda juga dapat melihatnya dari sudut pandang dukungan. Versi numpy "terdekat" (atau lainnya) tidak memiliki dukungan identik (dalam persentil) untuk setiap titik data, H&F memiliki dukungan yang sama untuk "terdekat" dan mungkin untuk titik tengah adalah C = 1/2, tidak yakin.
Saya terus mengulang sendiri, saya tidak tahu apakah argumen dukungan seperti itu (terhadap C = 1 seperti numpy menggunakannya), sebenarnya adalah alasan yang sebenarnya.

EDIT: titik tengah memiliki dukungan yang sama (untuk area di antara titik data, bukan untuk titik itu sendiri) dalam numpy, jadi dengan "C = 1"

@seberg Sepertinya tidak berhasil dengan saya. Dapatkah Anda memposting kode Anda yang menunjukkannya berfungsi?

Nah, saya salah tandai, di kode itu di atas sana, jadi sebaliknya (C = 0 a no-op bukan C = 1):

def scale_percentiles(p, num, C=0):
     """
     p : float
          percentiles to be used (within 0 and 100 inclusive)
     num : int
         number of data points.
     C : float
         parameter C, should be 0, 0.5 or 1. Numpy uses 1, matlab 0.5, H&F is 0.
     """
     p = np.asarray(p)
     fact = (num+1.-2*C)/(num-1)
     p *= fact
     p -= 0.5 * (fact-1) * 100
     p[p < 0] = 0
     p[p > 100] = 100
     return p
plt.figure()
plt.plot(np.percentile([0, 1, 2, 3], scale_percentiles(np.linspace(0, 100, 101), 5, C=0), interpolation='nearest'))
plt.plot(np.percentile([0, 1, 2, 3], scale_percentiles(np.linspace(0, 100, 101), 5, C=1), interpolation='nearest'))
plt.figure()
plt.plot(np.percentile([15, 20, 35, 40, 50], scale_percentiles(np.linspace(0, 100, 101), 5, C=1), interpolation='linear'))
plt.plot(np.percentile([15, 20, 35, 40, 50], scale_percentiles(np.linspace(0, 100, 101), 5, C=0.5), interpolation='linear'))
plt.plot(np.percentile([15, 20, 35, 40, 50], scale_percentiles(np.linspace(0, 100, 101), 5, C=0), interpolation='linear'))

@seberg Tutup tapi belum sampai di sana. Untuk a = [0,1,2,3] dan percentiles = [25, 50, 75, 100] , np.percentile (a, scale_percentiles(percentiles, len(a), C=0), interpolation='nearest) mengembalikan [0, 2, 3, 3] , ketika seharusnya mengembalikan [0,1,2,3] .

Saya harus membuat daftar persentil dtype=np.float atau fungsi Anda akan memberikan kesalahan, tapi menurut saya bukan itu masalahnya.

Fungsi metode klasik sederhana:
Persentil / 100 * N -> Jika itu bilangan bulat yang indeks, jika tidak, gunakan langit-langit sebagai indeks.

Meski begitu, argumen C sepertinya berjalan sesuai harapan, sehingga bisa diterapkan jika orang ingin menggunakannya untuk interpolasi. Saya masih ingin metode = 'classic' atau interpolation = 'none' yang akan berfungsi sebagai wikipedia.

Untuk debugging, ini adalah implementasi non-numpy jelek saya dari metode klasik:

def percentile (arr, p):
    arr = sorted(arr)

    index = p /100 * len(arr)

    # If index is a whole number, and larger than zero, subtract one unit (due to 0-based indexing)
    if index%1 < 0.0001 and index//1 > 0:
        index -= 1

    return arr[int(index)]

dan yang lebih numpythonic:

def indexes_classic(percentiles, set_size):
    percentiles = np.asarray(percentiles)

    indexes = percentiles / 100* set_size
    indexes[np.isclose(indexes%1, 0)] -= 1
    indexes = np.asarray(indexes, dtype=np.int)
    indexes[indexes < 0] = 0
    indexes[indexes > 100] = 100

    return indexes

Perbedaan tersebut terdengar seperti masalah floating point / rounding (yang Anda
sepertinya sadar), dan mungkin tebakan saya dengan C = 0 itu salah dan Anda mau
C = 0,5.
Maksud saya adalah mengatakan dari mana perbedaan itu berasal ("Parameter C"
IMO, meskipun mungkin ada alasan bagus untuk tidak menyukai banyak orang
kombinasi). Itu bukan untuk memberi Anda / menerapkan solusi.

Mengenai metode "klasik", saya terus terang tidak terlalu peduli yang klasik
seharusnya. Yang saya tahu, klasik hanya berarti "cukup banyak
orang menggunakannya ".

Solusi bijaksana, kesan pertama saya adalah "klasik" atau apa pun
nama, hanya menambahkan opsi lain yang membingungkan dengan nama yang tidak jelas. saya harap
bahwa diskusi ini bisa mengarah pada pembuatan semua
pilihan yang baik (umum) tersedia bagi pengguna secara bersih dan transparan
cara. Paling baik dalam cara yang mungkin dipahami orang.

Kita bisa menambahkan satu metode lagi, tapi terus terang saya hanya setengah menyukainya. Ketika kita
terakhir menambahkan lebih banyak metode (saya tidak ingat persis apa yang berubah)
sudah tertunda dan berharap seseorang akan melompat dan mencari tahu
apa yang harus kita miliki. Tak perlu dikatakan, itu tidak pernah benar-benar terjadi. Dan sekarang
Saya mencoba untuk menunjukkan perbedaan dan mencoba untuk melihat bagaimana itu cocok
dengan apa yang kita miliki saat ini.

Jadi, kesan saya adalah (dengan kemungkinan masalah dengan pembulatan dan tepat
persentil cocok) kita memiliki (mungkin terlalu) banyak opsi "interpolasi"
dan akan membutuhkan "parameter C" atau apa pun yang Anda inginkan untuk memanggilnya
dapat melakukan hampir semua hal.
Dan saya akan sangat senang jika seseorang bisa memberi tahu saya bagaimana semua itu
(Umum) "Metode" di luar sana termasuk dalam kategori tersebut, tampaknya
lebih dari C = 0,0.5,1 bahkan ada, dan mungkin beberapa bahkan di luar itu
pilihan....

Mungkin saya mengambil jalur yang salah, tetapi menambahkan "Metode1" dengan
nama tidak jelas yang tidak benar-benar memberi tahu siapa pun tentang perbedaannya dari
metode lain tampaknya tidak membantu saya (kecuali untuk seseorang yang
kebetulan sudah tahu nama "Metode1" dan sedang mencarinya. Dan
tolong jangan katakan bahwa "klasik" adalah yang jelas, itu ada
terlalu banyak variasi dalam implementasi di luar sana.

Cara lain mungkin dengan menghentikan "interpolasi", tetapi memiliki daftar
metode juga jauh kurang bagus kemudian mengisyaratkan "interpolasi linier"
mengatakan bahwa ini bukan perilaku melangkah, dll .... Dan jika kita melakukannya,
Saya masih menginginkan gambaran yang masuk akal.

Anda tidak harus melakukannya, tetapi jika kita ingin menambahkan metode baru, kita membutuhkan file
cara untuk menambahkannya yang tidak lagi membingungkan semua orang dan jelas!

Izinkan saya meringkasnya:

1) Saat ini numpy hanya menawarkan satu metode yang berguna: interpolation = 'linear', dan yang lainnya hanyalah variasi kecil di sekitarnya yang tampaknya tidak benar-benar digunakan oleh siapa pun. Paket lain memiliki lebih banyak opsi yang relevan.

2) Menambahkan nilai lain untuk C = 0 atau C = 0,5, masuk akal bagi saya. Semua metode interpolasi dapat bekerja dalam kombinasi dengan mereka, meskipun sekali lagi mereka mungkin tidak akan pernah digunakan.

3) Jika salah satu kombinasi antara metode interpolasi dan argumen C, berhasil meniru metode klasik (referensi dan wikipedia dan pengalaman pribadi saya setuju bahwa ini adalah metode yang paling umum diajarkan), maka saya senang dengan itu. Dapat dinyatakan di dokumen bahwa kombo tersebut menghasilkan metode non-interpolasi klasik. Saya tidak yakin apakah ini hanya karena masalah presisi float, tetapi saya menghargai upaya Anda untuk menanganinya dengan cara yang lebih terintegrasi!

4) Jika tidak ada kombo yang mencapai hasil yang sama, maka saya pikir metode yang berbeda akan masuk akal. Mungkin disebut interpolation = 'none' akan menjadi kurang membingungkan.

Singkatnya: opsi numpy.percentile saat ini tampak agak membingungkan dan terbatas. Makalah yang disebutkan di atas menawarkan gambaran umum yang baik tentang metode bermanfaat lainnya. Bersama dengan halaman wikipedia, mereka dapat bekerja sebagai titik awal untuk desain rangkaian pilihan yang lebih lengkap dan berguna untuk numpy.percentile. Semoga seseorang ingin mengerjakan tugas ini.

Apakah "terdekat" saat ini masuk akal dalam beberapa / kasus? Jika metode jarak ("C") atau apa pun yang membuat perbedaan besar untuk interpolasi linier / hal-hal pecahan, saya mungkin hanya terkejut tidak ada yang pernah melakukannya untuk perkiraan non-pecahan ?! Apakah dukungan konstan itu penting, dan ada alasan untuk membuang argumen invers CDF untuk metode interpolasi?

Kombo tidak berguna kecuali mereka dapat dimengerti dan yang umum digunakan mudah ditemukan, jadi saya meragukannya. Untuk interpolasi tampaknya ada banyak opsi (mis. Http://mathworld.wolfram.com/Quantile.html Q4 hingga Q9, menurut saya dokumentasi R secara praktis identik, tetapi menurut saya sepertinya tidak lengkap, misalnya matlab ...) Saya tidak tahu apakah mereka benar-benar masuk akal;).

Masalahnya adalah "interpolasi" menunjuk pada apa yang harus dilakukan di antara titik-titik yang didefinisikan dengan tepat, tetapi ada banyak (anehnya banyak) cara untuk menempatkan titik-titik tersebut setidaknya ketika menggunakan "interpolasi linier", jadi sepertinya pendekatan yang buruk untuk menambahkannya. Anda menginginkan "peringkat terdekat" yang terdengar banyak (dan ada dalam semangat) interpolasi = "terdekat", tetapi pilihan "posisi plot" yang tepat tampaknya "tidak standar", jadi tidak mungkin untuk menebak dan karenanya pilihan yang buruk.

Kemudian saya bahkan lebih memilih untuk mencela semuanya secara agresif (kecuali mungkin linier).

Tetapi, jika kita mencela, saya ingin membuatnya 100% benar, dan itu mungkin perlu sedikit lebih jelas tentang apa yang ada, apa yang harus ada dan apa yang seharusnya tidak ada.

saya sangat setuju dengan anda

@ RicardoV94 : Apakah Anda memiliki pendapat tentang definisi linear untuk kasus kuantil tertimbang yang diusulkan pada # 9211? Ada beberapa grafik di sana dengan gaya yang sama.

Mungkin @ ricardoV94 dapat mengomentarinya (itu akan keren), tapi menurut saya masalahnya cukup ortogonal. Bobot mungkin hanya bobot jenis frekuensi, dengan asumsi tidak ada bobot lain yang ditentukan secara wajar untuk persentil (saya tidak mengerti caranya), seharusnya tidak ada ambiguitas saat menerapkannya, tetapi saya tidak tahu pasti.

Anda juga dapat mencoba melakukan ping josef-pkt pada PR itu dan berharap dia memberikan komentar cepat apakah menurutnya itu ide yang bagus / benar.

Jika ada yang ingin mengambilnya dari sini, saya menulis fungsi yang tidak dioptimalkan yang menghitung file
9 metode estimasi persentil / kuantil dijelaskan oleh Hyndman dan Fan (1996) dan juga digunakan dalam R.

Metode 1 sesuai dengan 'metode peringkat terdekat klasik' seperti yang dibahas di Wikipedia . Metode 7 setara dengan implementasi Numpy saat ini (interpolasi = 'linier'). Metode interpolasi Numpy yang tersisa tidak disertakan (dan tampaknya tidak berguna).

def percentile(x, p, method=7):
    '''
    Compute the qth percentile of the data.

    Returns the qth percentile(s) of the array elements.

    Parameters
    ----------
    x : array_like
        Input array or object that can be converted to an array.
    p : float in range of [0,100] (or sequence of floats)
        Percentile to compute, which must be between 0 and 100 inclusive.
    method : integer in range of [1,9]
        This optional parameter specifies one of the nine sampling methods 
        discussed in Hyndman and Fan (1996). 

        Methods 1 to 3 are discontinuous:
        * Method 1: Inverse of empirical distribution function (oldest
        and most studied method).
        * Method 2: Similar to type 1 but with averaging at discontinuities.
        * Method 3: SAS definition: nearest even order statistic.

        Methods 4 to 9 are continuous and equivalent to a linear interpolation 
        between the points (pk,xk) where xk is the kth order statistic. 
        Specific expressions for pk are given below:
        * Method 4: pk=kn. Linear interpolation of the empirical cdf.
        * Method 5: pk=(k−0.5)/n. Piecewise linear function where the knots 
        are the values midway through the steps of the empirical cdf 
        (Popular amongst hydrologists, used by Mathematica?).
        * Method 6: pk=k/(n+1), thus pk=E[F(xk)]. The sample space is divided
        in n+1 regions, each with probability of 1/(n+1) on average
        (Used by Minitab and SPSS).
        * Method 7: pk=(k−1)/(n−1), thus pk=mode[F(xk)]. The sample space
        is divided into n-1 regions (This is the default method of 
        Numpy, R, S, and MS Excell).
        * Method 8: pk=(k−1/3)/(n+1/3), thus pk≈median[F(xk)]. The resulting
        estimates are approximately median-unbiased regardless of the
        distribution of x (Recommended by Hyndman and Fan (1996)).
        * Method 9: k=(k−3/8)/(n+1/4), thus pk≈F[E(xk)]if x is normal (?).
        The resulting estimates are approximately unbiased for the expected 
        order statistics if x is normally distributed (Used for normal QQ plots).

        References:
        Hyndman, R. J. and Fan, Y. (1996) Sample quantiles in statistical packages, 
        American Statistician 50, 361--365.
        Schoonjans, F., De Bacquer, D., & Schmid, P. (2011). Estimation of population
        percentiles. Epidemiology (Cambridge, Mass.), 22(5), 750.

        '''

    method = method-1    
    x = np.asarray(x)
    x.sort()
    p = np.array(p)/100

    n = x.size  
    m = [0, 0, -0.5, 0, 0.5, p, 1-p, (p+1)/3, p/4+3/8][method]

    npm = n*p+m
    j = np.floor(npm).astype(np.int)
    g = npm-j

    # Discontinuous functions
    if method < 3:
        yg0 = [0, 0.5, 0][method]
        y = np.ones(p.size)
        if method < 2:
            y[g==0] = yg0
        else:
            y[(g==0) & (j%2 == 0)] = yg0      
    # Continuous functions
    else:
        y = g

    # Adjust indexes to work with Python
    j_ = j.copy()
    j[j<=0] = 1
    j[j > n] = n
    j_[j_ < 0] = 0
    j_[j_ >= n] = n-1 

    return (1-y)* x[j-1] + y*x[j_]

Metode berkelanjutan juga dapat diterapkan dengan lebih efisien seperti ini.

def percentile_continuous(x, p, method=7):
    '''
    Compute the qth percentile of the data.

    Returns the qth percentile(s) of the array elements.

    Parameters
    ----------
    x : array_like
        Input array or object that can be converted to an array.
    p : float in range of [0,100] (or sequence of floats)
        Percentile to compute, which must be between 0 and 100 inclusive.
    method : integer in range of [4,9]
        This optional parameter specifies one of the 5 continuous sampling
        methods discussed in Hyndman and Fan (1996). 
        '''

    x = np.asarray(x)
    x.sort()
    p = np.asarray(p)/100
    n = x.size

    if method == 4:
        r = p * n
    elif method == 5:
        r = p * n + .5
    elif method == 6:
        r = p * (n+1)
    elif method == 7:
        r = p * (n-1) + 1
    elif method == 8:
        r = p * (n+1/3) + 1/3
    elif method == 9:
        r = p * (n+1/4) + 3/8

    index = np.floor(r).astype(np.int)

    # Adjust indexes to work with Python
    index_ = index.copy()
    index[index_ <= 0] = 1
    index[index_  > n] = n
    index_[index_ < 0] = 0
    index_[index_ >= n] = n-1

    i = x[index - 1]
    j = x[index_]

    return i + r%1* (j-i)

Ada yang mau mengambilnya dari sini? Saya tidak memenuhi syarat untuk melakukannya.

Seperti yang disebutkan di posting sebelumnya, tampaknya implementasi default numpy saat ini dari kuantil cocok dengan R .

Di R :

> quantile(c(15, 20, 35, 40, 50), probs=c(0.05, 0.3, 0.4, 0.5, 1))
  5%  30%  40%  50% 100% 
  16   23   29   35   50 
> quantile(c(3, 6, 7, 8, 8, 10, 13, 15, 16, 20), probs=c(0.25, 0.5, 0.75, 1))
  25%   50%   75%  100% 
 7.25  9.00 14.50 20.00
> quantile(c(3, 6, 7, 8, 8, 9, 10, 13, 15, 16, 20), probs=c(0.25, 0.5, 0.75, 1))
 25%  50%  75% 100% 
 7.5  9.0 14.0 20.0 

Di np.quantile :

>>> np.quantile([15, 20, 35, 40, 50], q=[0.05, 0.3, 0.4, 0.5, 1])
array([16., 23., 29., 35., 50.])
>>> np.quantile([3, 6, 7, 8, 8, 10, 13, 15, 16, 20], q=[0.25, 0.5, 0.75, 1])
array([ 7.25,  9.  , 14.5 , 20.  ])
>>> np.quantile([3, 6, 7, 8, 8, 9, 10, 13, 15, 16, 20], q=[0.25, 0.5, 0.75, 1])
array([ 7.5,  9. , 14. , 20. ])

yang tentu saja tidak mereproduksi contoh yang diberikan di Wikipedia:
https://en.wikipedia.org/wiki/Percentile

Faktanya, jika Anda membuka halaman bantuan R untuk kuantil https://www.rdocumentation.org/packages/stats/versions/3.5.0/topics/quantile
Anda akan melihat bahwa metode default R (Tipe 7) menetapkan kondisi batas yang identik dengan cara np.quantile menetapkannya: p_k = (k-1) / (n-1) , di mana n adalah ukuran sampel, dan k = 1 menunjukkan yang terkecil nilai, sedangkan k = n terbesar. Itu berarti nilai terkecil dalam larik yang diurutkan disematkan pada jumlah = 0, dan yang terbesar disematkan pada jumlah = 1.

Juga seperti yang disebutkan di posting sebelumnya, Anda dapat mereproduksi 3 contoh di Wikipedia dengan Tipe 1:

> quantile(c(15, 20, 35, 40, 50), probs=c(0.05, 0.3, 0.4, 0.5, 1), type=1)
  5%  30%  40%  50% 100% 
  15   20   20   35   50 
> quantile(c(3, 6, 7, 8, 8, 10, 13, 15, 16, 20), probs=c(0.25, 0.5, 0.75, 1), type=1)
 25%  50%  75% 100% 
   7    8   15   20 
> quantile(c(3, 6, 7, 8, 8, 9, 10, 13, 15, 16, 20), probs=c(0.25, 0.5, 0.75, 1), type=1)
 25%  50%  75% 100% 
   7    9   15   20 

Itu menimbulkan beberapa pertanyaan menarik:

1.) haruskah default np.quantile melacak default R.quantile?
2.) haruskah np.quantile beralih ke algoritma Tipe 1?

Karena bahkan Wikipedia sendiri setuju bahwa tidak ada definisi standar dari persentil, saya pikir selama algoritme tersebut kuat dan pengguna mengetahui cara kerjanya, baik (1) atau (2) tidak terlalu penting. Saya lebih menyukai (1) karena Python dan R adalah dua platform analisis data paling populer di luar sana, dan alangkah baiknya jika mereka dapat saling memeriksa. Mengingat itu, saya pikir (2) tidak perlu.

Ya, R dan Numpy default ke metode 7 dan harus tetap seperti itu. Pertanyaannya adalah tentang menambahkan metode lain atau tidak.

Jika ada yang tertarik, saya memasang modul independen dengan metode persentil 9, di sini . Jangan ragu untuk menggunakannya atau beradaptasi dengan Numpy jika Anda tahu caranya.

Terima kasih @ ricardoV94 .

Jadi, hanya untuk iseng, saya melakukan jajak pendapat di tempat kerja pada pengguna R. Dari 20 orang yang menanggapi, 20 hanya menggunakan metode default di quantile . Mereka berkisar dari mahasiswa Magister kesehatan masyarakat hingga peneliti PhD dalam Statistik.

Secara pribadi, saya tidak yakin apakah itu sepadan dengan usaha numpy untuk mendukung 9 cara berbeda untuk menghitung kuantil. Saya pikir sebagian besar pengguna hanya akan menggunakan default.

Untuk apa nilainya ada fungsi scipy.stats.mstats.mquantiles yang mendukung 6 dari 9 metode (yang berkelanjutan) dan dokumen menyatakan secara eksplisit tautan dengan implementasi R.

@albertcthomas ah, senang mengetahuinya. Meskipun, saya pikir idealnya kita akan menyembunyikan kompleksitas ini sedikit. Dan kebanyakan kita perlu memperbaiki versi IIRC yang tidak bersebelahan. Karena itu pada dasarnya tidak memberikan metode yang paling umum.

Ya, numpy mungkin tidak harus mendukung metode ini jika diterapkan dalam modul statistik scipy.

Secara pribadi saya akan memilih metode yang menghitung kuantitas dari invers umum dari fungsi distribusi kumulatif. Fakta bahwa metode seperti itu tidak tersedia membawa saya ke masalah ini :).

@albertcthomas jika kamu punya petunjuk / pengetahuan tentang ini, tolong katakan! Kami agak mandek karena kurang jelasnya default apa yang bagus. Dan menurut saya ini adalah masalah yang cukup mengganggu.

Yang terpenting, kami membutuhkan beberapa default yang bagus. Dan itu mungkin berarti menerapkan 2-3 metode (sepenuhnya mengubah metode yang tidak bersebelahan). Saya baik-baik saja dengan mendukung hal-hal yang lebih banyak atau lebih kompleks, tetapi saya akan senang jika kita dapat memutuskan beberapa yang "biasa / bagus".

Saya akan mengatakan bahwa metode linier (default saat ini) dan kebalikan dari fungsi distribusi kumulatif (yang saya cari ketika saya membuat Masalah ini, serta @albertcthomas jika saya mengerti dengan benar) sudah cukup. Pada dasarnya ini memungkinkan seseorang untuk memilih apakah mereka ingin interpolasi atau tidak.

Dan alternatif lain yang saat ini diterapkan harus dihilangkan.

Kebalikan dari fungsi distribusi kumulatif harus ditambahkan. Ini adalah salah satu penduga yang paling populer dari suatu kuantil dari sampel pengamatan tertentu dalam statistik.

Dan alternatif lain yang saat ini diterapkan harus dihilangkan.

@ ricardoV94 Apakah Anda mengatakan ini karena tidak ada alternatif yang dirujuk di Wikipedia maupun makalah Hyndman dan Fan?

Ya, afaik tidak diimplementasikan dalam paket lain.

Saya tidak mengerti mengapa ada orang yang ingin menggunakan metode itu, dan nama mereka adalah
juga berpotensi menyesatkan.

Albert Thomas [email protected] escreveu no dia quarta, 2/01/2019
à 14:18:

Dan alternatif lain yang saat ini diterapkan pasti harus dilakukan
dihapus.

@ ricardoV94 https://github.com/ricardoV94 apakah Anda mengatakan ini karena
tidak ada alternatif yang dirujuk di Wikipedia atau Hyndman dan
Kertas kipas?

-
Anda menerima ini karena Anda disebutkan.
Balas email ini secara langsung, lihat di GitHub
https://github.com/numpy/numpy/issues/10736#issuecomment-450861068 , atau nonaktifkan
utasnya
https://github.com/notifications/unsubscribe-auth/AbpAmfUoJNk3YHOSHNeVN03Va5wtvkHQks5u_LGugaJpZM4SnVpE
.

Terima kasih! Mengapa tidak membuka PR untuk menambahkan invers dari distribusi kumulatif sebagai metode yang tersedia di np.percentile? sembari tetap membuka masalah ini jika kita ingin terus berdiskusi tentang alternatif (kecuali default saat ini yang harus tetap default). Bagaimana deprecation ditangani secara numpy?

Beberapa informasi lebih lanjut di sini - Python 3.8 menambahkan statistics.quantiles - kita harus mempertimbangkan untuk menambahkan mode yang setara ke np.quantile

Cara maju di sini mungkin dengan menambahkan method kwarg mencerminkan statistics one, dan mungkin menambahkan 0-2 lagi (dalam hal ini akan lebih baik untuk melakukan ping ke penulis asli di python) .

Saya tidak yakin apakah defaultnya cocok antara milik kami dan milik mereka, yang akan memalukan jika tidak, tetapi sepertinya masih ide terbaik (dan cukup banyak yang ada dalam pikiran kami). 0-2 "metode" baru juga boleh ditambahkan. Dalam hal ini akan lebih baik untuk melakukan ping ke statistik python pada nama sebenarnya ...

Humas sangat menyambut, saya ingin ini terus berlanjut, tetapi saya tidak akan melakukannya dalam waktu dekat.

@ eric-wieser Saya perhatikan bahwa Anda memiliki beberapa PR terkait yang luar biasa, apakah ada di antara mereka yang menangani hal ini?

Saya akan mendorong ini ke 1,19 jadi ini bukan pemblokir. Tetapi itu tidak berarti itu tidak dapat diperbaiki untuk 1,18 :)

@charris : PR mana yang Anda pikirkan?

Sayangnya, saya rasa belum ada yang menuju ke arah ini.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat