Tôi có nhiều danh sách số nguyên lớn (> 35.000.000) sẽ chứa các bản sao. Tôi cần lấy số đếm cho mỗi số nguyên trong một danh sách. Mã sau hoạt động, nhưng có vẻ chậm. Bất cứ ai có thể tốt hơn các điểm chuẩn bằng cách sử dụng Python và tốt nhất là Numpy?Nhóm kết quả bằng cách sử dụng itertools.groupby hiệu suất
def group():
import numpy as np
from itertools import groupby
values = np.array(np.random.randint(0,1<<32,size=35000000),dtype='u4')
values.sort()
groups = ((k,len(list(g))) for k,g in groupby(values))
index = np.fromiter(groups,dtype='u4,u2')
if __name__=='__main__':
from timeit import Timer
t = Timer("group()","from __main__ import group")
print t.timeit(number=1)
trả về:
$ python bench.py
111.377498865
Cheers!
Sửa dựa trên phản ứng:
def group_original():
import numpy as np
from itertools import groupby
values = np.array(np.random.randint(0,1<<32,size=35000000),dtype='u4')
values.sort()
groups = ((k,len(list(g))) for k,g in groupby(values))
index = np.fromiter(groups,dtype='u4,u2')
def group_gnibbler():
import numpy as np
from itertools import groupby
values = np.array(np.random.randint(0,1<<32,size=35000000),dtype='u4')
values.sort()
groups = ((k,sum(1 for i in g)) for k,g in groupby(values))
index = np.fromiter(groups,dtype='u4,u2')
def group_christophe():
import numpy as np
values = np.array(np.random.randint(0,1<<32,size=35000000),dtype='u4')
values.sort()
counts=values.searchsorted(values, side='right') - values.searchsorted(values, side='left')
index = np.zeros(len(values),dtype='u4,u2')
index['f0']=values
index['f1']=counts
#Erroneous result!
def group_paul():
import numpy as np
values = np.array(np.random.randint(0,1<<32,size=35000000),dtype='u4')
values.sort()
diff = np.concatenate(([1],np.diff(values)))
idx = np.concatenate((np.where(diff)[0],[len(values)]))
index = np.empty(len(idx)-1,dtype='u4,u2')
index['f0']=values[idx[:-1]]
index['f1']=np.diff(idx)
if __name__=='__main__':
from timeit import Timer
timings=[
("group_original","Original"),
("group_gnibbler","Gnibbler"),
("group_christophe","Christophe"),
("group_paul","Paul"),
]
for method,title in timings:
t = Timer("%s()"%method,"from __main__ import %s"%method)
print "%s: %s secs"%(title,t.timeit(number=1))
trả về:
$ python bench.py
Original: 113.385262966 secs
Gnibbler: 71.7464978695 secs
Christophe: 27.1690568924 secs
Paul: 9.06268405914 secs
Mặc dù Christophe cho kết quả không chính xác hiện
Có bất kỳ hạn chế nào đối với phạm vi các số nguyên có thể không? Có thể tất cả 2^32 số nguyên có thể xảy ra không? –
Bạn có cần đầu ra của 'nhóm()' được sắp xếp theo khóa không? –
Hi Sven, có một cơ hội bình đẳng của mỗi 2^32 số nguyên xảy ra và đầu ra được nhóm (tức là chỉ mục) cần phải theo thứ tự tăng dần. Các giá trị.sort() không thực sự là nút cổ chai, đó là dòng cuối cùng của nhóm() là bit chậm! Chúc mừng! – Donny