Saya memiliki beberapa array besar (~100 juta poin) yang perlu saya plot secara interaktif. Saya saat ini menggunakan Matplotlib. Merencanakan array sebagaimana adanya menjadi sangat lambat dan sia-sia karena Anda tidak dapat memvisualisasikan poin sebanyak itu.
Jadi saya membuat fungsi penipisan min/maks yang saya ikat ke panggilan balik 'xlim_changed' dari sumbu. Saya menggunakan pendekatan min/maks karena datanya berisi lonjakan cepat yang tidak ingin saya lewatkan hanya dengan menelusuri datanya. Ada lebih banyak pembungkus yang dipotong hingga batas x, dan melewatkan pemrosesan dalam kondisi tertentu, tetapi bagian yang relevan ada di bawah:
def min_max_downsample(x,y,num_bins):
""" Break the data into num_bins and returns min/max for each bin"""
pts_per_bin = x.size // num_bins
#Create temp to hold the reshaped & slightly cropped y
y_temp = y[:num_bins*pts_per_bin].reshape((num_bins, pts_per_bin))
y_out = np.empty((num_bins,2))
#Take the min/max by rows.
y_out[:,0] = y_temp.max(axis=1)
y_out[:,1] = y_temp.min(axis=1)
y_out = y_out.ravel()
#This duplicates the x-value for each min/max y-pair
x_out = np.empty((num_bins,2))
x_out[:] = x[:num_bins*pts_per_bin:pts_per_bin,np.newaxis]
x_out = x_out.ravel()
return x_out, y_out
Ini berfungsi cukup baik dan cukup cepat (~80ms pada 1e8 poin & 2k bin). Ada sedikit jeda karena secara berkala menghitung ulang & memperbarui data x & y jalur.
Namun, satu-satunya keluhan saya ada pada x-data. Kode ini menduplikasi nilai x dari setiap tepi kiri wadah dan tidak mengembalikan lokasi x sebenarnya dari pasangan y min/maks. Saya biasanya mengatur jumlah nampan untuk menggandakan lebar piksel sumbu. Jadi Anda tidak bisa melihat perbedaannya karena tempat sampahnya sangat kecil...tapi saya tahu itu ada di sana... dan itu mengganggu saya.
Jadi coba nomor 2 yang mengembalikan nilai x aktual untuk setiap pasangan min/maks. Namun itu sekitar 5x lebih lambat.
def min_max_downsample_v2(x,y,num_bins):
pts_per_bin = x.size // num_bins
#Create temp to hold the reshaped & slightly cropped y
y_temp = y[:num_bins*pts_per_bin].reshape((num_bins, pts_per_bin))
#use argmax/min to get column locations
cc_max = y_temp.argmax(axis=1)
cc_min = y_temp.argmin(axis=1)
rr = np.arange(0,num_bins)
#compute the flat index to where these are
flat_max = cc_max + rr*pts_per_bin
flat_min = cc_min + rr*pts_per_bin
#Create a boolean mask of these locations
mm_mask = np.full((x.size,), False)
mm_mask[flat_max] = True
mm_mask[flat_min] = True
x_out = x[mm_mask]
y_out = y[mm_mask]
return x_out, y_out
Ini membutuhkan waktu sekitar 400+ ms di mesin saya yang menjadi cukup terlihat. Jadi pertanyaan saya pada dasarnya adalah apakah ada cara untuk bekerja lebih cepat dan memberikan hasil yang sama? Kemacetan sebagian besar terjadi pada fungsi numpy.argmin
dan numpy.argmax
yang sedikit lebih lambat dibandingkan numpy.min
dan numpy.max
.
Jawabannya mungkin hanya menggunakan versi #1 karena secara visual tidak terlalu penting. Atau mungkin mencoba mempercepatnya dengan sesuatu seperti cython (yang belum pernah saya gunakan).
FYI menggunakan Python 3.6.4 di Windows... contoh penggunaannya akan seperti ini:
x_big = np.linspace(0,10,100000000)
y_big = np.cos(x_big )
x_small, y_small = min_max_downsample(x_big ,y_big ,2000) #Fast but not exactly correct.
x_small, y_small = min_max_downsample_v2(x_big ,y_big ,2000) #correct but not exactly fast.
set_data
dari baris yang ada di matplotlib. - person user2699   schedule 31.01.2019