ฉันมีอาร์เรย์ขนาดใหญ่ (ประมาณ 100 ล้านจุด) ที่ฉันต้องลงจุดแบบโต้ตอบ ฉันกำลังใช้ Matplotlib การพล็อตอาร์เรย์ตามที่เป็นอยู่จะช้ามากและเป็นการสิ้นเปลืองเนื่องจากคุณไม่สามารถเห็นภาพหลายจุดได้
ดังนั้นฉันจึงสร้างฟังก์ชันการทศนิยมขั้นต่ำ/สูงสุดที่ฉันเชื่อมโยงกับการเรียกกลับ 'xlim_changed' ของแกน ฉันเลือกใช้วิธีต่ำสุด/สูงสุด เนื่องจากข้อมูลมีการเพิ่มขึ้นอย่างรวดเร็วซึ่งฉันไม่อยากพลาดเพียงแค่ดูข้อมูลทีละขั้นตอน มี Wrapper อื่นๆ ที่ครอบตัดจนถึงขีดจำกัด x และข้ามการประมวลผลภายใต้เงื่อนไขบางประการ แต่ส่วนที่เกี่ยวข้องอยู่ด้านล่าง:
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
ใช้งานได้ค่อนข้างดีและเร็วเพียงพอ (~ 80ms บน 1e8 คะแนน & 2k bins) มีความล่าช้าน้อยมากเนื่องจากมีการคำนวณใหม่และอัปเดตข้อมูล x & y ของบรรทัดเป็นระยะ
อย่างไรก็ตาม ข้อร้องเรียนเดียวของฉันอยู่ใน x-data โค้ดนี้จำลองค่า x ของขอบด้านซ้ายของแต่ละถังขยะ และจะไม่ส่งคืนตำแหน่ง x ที่แท้จริงของคู่ค่า y min/max โดยทั่วไปฉันจะตั้งค่าจำนวนถังขยะให้เพิ่มความกว้างพิกเซลของแกนเป็นสองเท่า คุณจึงมองไม่เห็นความแตกต่างเพราะถังขยะมีขนาดเล็กมาก...แต่ฉันรู้ว่ามันอยู่ตรงนั้น... และมันทำให้ฉันรำคาญ
ดังนั้นลองหมายเลข 2 ซึ่งจะคืนค่า x จริงสำหรับคู่ต่ำสุด/สูงสุดทุกคู่ แต่ช้ากว่าประมาณ 5 เท่า
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
ใช้เวลาประมาณ 400+ ms บนเครื่องของฉันซึ่งค่อนข้างสังเกตได้ชัดเจน โดยพื้นฐานแล้วคำถามของฉันคือมีวิธีใดที่จะเร็วขึ้นและให้ผลลัพธ์เหมือนเดิมหรือไม่ คอขวดส่วนใหญ่อยู่ในฟังก์ชัน numpy.argmin
และ numpy.argmax
ซึ่งช้ากว่า numpy.min
และ numpy.max
เล็กน้อย
คำตอบอาจเป็นแค่ใช้งานเวอร์ชัน #1 เนื่องจากรูปลักษณ์ไม่สำคัญ หรืออาจลองเร่งความเร็วบางอย่างเช่น cython (ซึ่งฉันไม่เคยใช้)
FYI โดยใช้ Python 3.6.4 บน Windows ... ตัวอย่างการใช้งานจะเป็นดังนี้:
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
ของบรรทัดที่มีอยู่ใน matplotlib - person user2699   schedule 31.01.2019