Oto kod ilustrujący rozmiar problemu (stan na 11 maja 2015 r.) I sposób jego "naprawienia".
import numpy as np
import bisect
import timeit
from random import randint
dtype = np.dtype([ ('pos','<I'),('sig','<H') ]) # my data is unsigned 32bit, and unsigned 16bit
data1 = np.fromfile('./all2/840d.0a9b45e8c5344abf6ac761017e93b5bb.2.1bp.binary', dtype)
dtype2 = np.dtype([('pos',np.uint32),('sig',np.uint32)]) # convert data to both unsigned 32bit
data2 = data1.astype(dtype2)
data3 = data2.view(('uint32', len(data2.dtype.names))) # convert above to a normal array (not structured array)
print data1.dtype.descr # [('pos', '<u4'), ('sig', '<u2')]
print data2.dtype.descr # [('pos', '<u4'), ('sig', '<u4')]
print data3.dtype.descr # [('', '<u4')]
print data1.nbytes # 50344494
print data2.nbytes # 67125992
print data3.nbytes # 67125992
print data1['pos'].max() # 2099257376
print data2['pos'].max() # 2099257376
print data3[:,0].max() # 2099257376
def b1(): return bisect.bisect_left(data1['pos'], randint(100000000,200000000))
def b2(): return bisect.bisect_left(data2['pos'], randint(100000000,200000000))
def b3(): return bisect.bisect_left(data3[:,0], randint(100000000,200000000))
def ss1(): return np.searchsorted(data1['pos'], randint(100000000,200000000))
def ss2(): return np.searchsorted(data2['pos'], randint(100000000,200000000))
def ss3(): return np.searchsorted(data3[:,0], randint(100000000,200000000))
def ricob1(): return bisect.bisect_left(data1['pos'], np.uint32(randint(100000000,200000000)))
def ricob2(): return bisect.bisect_left(data2['pos'], np.uint32(randint(100000000,200000000)))
def ricob3(): return bisect.bisect_left(data3[:,0], np.uint32(randint(100000000,200000000)))
def ricoss1(): return np.searchsorted(data1['pos'], np.uint32(randint(100000000,200000000)))
def ricoss2(): return np.searchsorted(data2['pos'], np.uint32(randint(100000000,200000000)))
def ricoss3(): return np.searchsorted(data3[:,0], np.uint32(randint(100000000,200000000)))
print timeit.timeit(b1,number=300) # 0.0085117816925
print timeit.timeit(b2,number=300) # 0.00826191902161
print timeit.timeit(b3,number=300) # 0.00828003883362
print timeit.timeit(ss1,number=300) # 6.57477498055
print timeit.timeit(ss2,number=300) # 5.95308589935
print timeit.timeit(ss3,number=300) # 5.92483091354
print timeit.timeit(ricob1,number=300) # 0.00120902061462
print timeit.timeit(ricob2,number=300) # 0.00120401382446
print timeit.timeit(ricob3,number=300) # 0.00120711326599
print timeit.timeit(ricoss1,number=300) # 4.39265394211
print timeit.timeit(ricoss2,number=300) # 0.00116586685181
print timeit.timeit(ricoss3,number=300) # 0.00108909606934
Aktualizacja! Dzięki komentarzom Rico wygląda na to, że ustawiasz typ dla numeru, który chcesz przeszukać/bisect jest naprawdę importowany! Jednak na tablicy strukturalnej z 32-bitowym i 16-bitowym numerem int, nadal jest wolna (choć nie jest tak blisko jak poprzednio).
Należy zauważyć, że jeśli tablica jest wystarczająco duża, różnica między wartością bisect i searchsorted jest znacząca, wtedy czas potrzebny do .copy() tej kolumny, użyj go do wyszukiwania z wyszukiwań, a następnie uzyskaj dane według indeksu searchsorted najprawdopodobniej będzie większy niż różnica między bisect i mergesorted na początek. Plus RAM. (ale 5/5 Bi Rico, aby dowiedzieć się, jaki jest format tego problemu) –
@ user3329564 Wierzę, że w pewnym momencie była łata, ale nie pamiętam, w której wersji się znalazła. –
Używam numpy '1.10.1' i otrzymuję zachowanie przeciwne:' timeit a ['f0']. Searchsorted (400.) 'jest' najlepszym z 3: 8.1 μs na pętlę' i 'timeit f0.searchsorted (400.) 'jest' najlepszym z 3: 510 ns na pętlę'. Zastanawiam się, dlaczego tak jest. – snowleopard