Berkaitan dengan jawaban ini , apakah ada cara cepat untuk menghitung median atas array yang memiliki grup dengan jumlah elemen yang tidak sama ?
Misalnya:
data = [1.00, 1.05, 1.30, 1.20, 1.06, 1.54, 1.33, 1.87, 1.67, ... ]
index = [0, 0, 1, 1, 1, 1, 2, 3, 3, ... ]
Dan kemudian saya ingin menghitung perbedaan antara jumlah dan median per kelompok (misalnya median dari kelompok 0
adalah 1.025
sehingga hasil pertama adalah 1.00 - 1.025 = -0.025
). Jadi untuk array di atas, hasilnya akan muncul sebagai:
result = [-0.025, 0.025, 0.05, -0.05, -0.19, 0.29, 0.00, 0.10, -0.10, ...]
Karena np.median.reduceat
belum ada, apakah ada cara cepat lain untuk mencapai ini? Array saya akan berisi jutaan baris sehingga kecepatan sangat penting!
Indeks dapat dianggap berdampingan dan dipesan (mudah untuk mengubahnya jika tidak).
Contoh data untuk perbandingan kinerja:
import numpy as np
np.random.seed(0)
rows = 10000
cols = 500
ngroup = 100
# Create random data and groups (unique per column)
data = np.random.rand(rows,cols)
groups = np.random.randint(ngroup, size=(rows,cols)) + 10*np.tile(np.arange(cols),(rows,1))
# Flatten
data = data.ravel()
groups = groups.ravel()
# Sort by group
idx_sort = groups.argsort()
data = data[idx_sort]
groups = groups[idx_sort]
python
performance
numpy
median
numpy-ufunc
Jean-Paul
sumber
sumber
scipy.ndimage.median
saran dalam jawaban yang ditautkan? Bagi saya tampaknya tidak membutuhkan jumlah elemen yang sama per label. Atau apakah saya melewatkan sesuatu?Jawaban:
Terkadang Anda perlu menulis kode numpy non-idiomatis jika Anda benar - benar ingin mempercepat perhitungan Anda yang tidak dapat Anda lakukan dengan numpy asli.
numba
mengkompilasi kode python Anda ke level C. rendah. Karena banyak numpy itu sendiri biasanya secepat C, ini sebagian besar akhirnya berguna jika masalah Anda tidak cocok dengan vektorisasi asli dengan numpy. Ini adalah salah satu contoh (di mana saya berasumsi bahwa indeks berdekatan dan diurutkan, yang juga tercermin dalam contoh data):Dan berikut adalah beberapa timing menggunakan
%timeit
keajaiban IPython :Menggunakan contoh data yang diperbarui dalam pertanyaan angka-angka ini (yaitu runtime dari fungsi python vs runtime dari JT-accelerated functio) adalah
Ini berarti 65x speedup dalam case yang lebih kecil dan 26x speedup dalam case yang lebih besar (dibandingkan dengan kode gila, tentu saja) menggunakan kode akselerasi. Kelebihan lainnya adalah bahwa (tidak seperti vektorisasi khas dengan numpy asli) kami tidak memerlukan memori tambahan untuk mencapai kecepatan ini, ini semua tentang kode tingkat rendah yang dioptimalkan dan disusun yang akhirnya dijalankan.
Fungsi di atas mengasumsikan bahwa array int numpy secara
int64
default, yang sebenarnya tidak terjadi pada Windows. Jadi alternatifnya adalah menghapus tanda tangan dari panggilan kenumba.njit
, memicu kompilasi tepat waktu yang tepat. Tetapi ini berarti bahwa fungsi tersebut akan dikompilasi selama eksekusi pertama, yang dapat mencampuri hasil pengaturan waktu (kita dapat mengeksekusi fungsi tersebut secara manual, menggunakan tipe data yang representatif, atau hanya menerima bahwa eksekusi pengaturan waktu pertama akan jauh lebih lambat, yang seharusnya diabaikan). Ini persis apa yang saya coba cegah dengan menentukan tanda tangan, yang memicu kompilasi sebelumnya.Bagaimanapun, dalam kasus JIT yang tepat dekorator yang kita butuhkan adalah adil
Perhatikan bahwa timing di atas yang saya perlihatkan untuk fungsi yang dikompilasi jit hanya berlaku setelah fungsi dikompilasi. Ini bisa terjadi pada definisi (dengan kompilasi bersemangat, ketika tanda tangan eksplisit diteruskan ke
numba.njit
), atau selama panggilan fungsi pertama (dengan kompilasi malas, ketika tidak ada tanda tangan dilewatkan kenumba.njit
). Jika fungsi ini hanya akan dieksekusi sekali maka waktu kompilasi juga harus dipertimbangkan untuk kecepatan metode ini. Biasanya hanya layak mengkompilasi fungsi jika total waktu kompilasi + eksekusi kurang dari runtime yang tidak dikompilasi (yang sebenarnya benar dalam kasus di atas, di mana fungsi python asli sangat lambat). Ini sebagian besar terjadi ketika Anda sering memanggil fungsi yang dikompilasi.Seperti yang dicatat oleh max9111 dalam komentar, salah satu fitur penting
numba
adalahcache
kata kunci untukjit
. Passingcache=True
tonumba.jit
akan menyimpan fungsi yang dikompilasi ke disk, sehingga selama eksekusi berikutnya dari modul python yang diberikan fungsi akan dimuat dari sana daripada dikompilasi ulang, yang lagi-lagi dapat membantu Anda menjalankan runtime dalam jangka panjang.sumber
index
data roganjosh . Saya akan meninggalkan catatan tentang ini, terima kasih :)cache=True
untuk menghindari kompilasi ulang pada setiap restart penerjemah.Salah satu pendekatan akan digunakan di
Pandas
sini murni untuk memanfaatkangroupby
. Saya telah menggembungkan ukuran input sedikit untuk memberikan pemahaman yang lebih baik tentang timing (karena ada overhead dalam membuat DF).Memberi yang berikut
timeit
:Untuk ukuran sampel yang sama, saya mendapatkan pendekatan dict dari Aryerez menjadi:
Namun, jika kita menambah input dengan faktor lain 10, waktunya menjadi:
Namun, dengan mengorbankan beberapa kemudahan, jawaban oleh Divakar menggunakan numpy murni muncul di:
Mengingat dataset baru (yang seharusnya sudah ditetapkan di awal):
sumber
Mungkin Anda sudah melakukan ini, tetapi jika tidak, lihat apakah itu cukup cepat:
Keluaran:
sumber
np.vectorize
adalah pembungkus yang sangat tipis untuk sebuah loop, jadi saya tidak akan mengharapkan pendekatan ini menjadi sangat cepat.data
danindex
sebagainp.array
sebagai dalam pertanyaan.Berikut adalah pendekatan berbasis NumPy untuk mendapatkan binned-median untuk nilai nampan / indeks positif -
Untuk mengatasi kasus spesifik kami yang dikurangkan -
sumber
df.groupby('index').transform('median')
?