Bộ lọc ngưỡng hiệu quả của một mảng có numpy


81

Tôi cần lọc một mảng để loại bỏ các phần tử thấp hơn một ngưỡng nhất định. Mã hiện tại của tôi như thế này:

threshold = 5
a = numpy.array(range(10)) # testing data
b = numpy.array(filter(lambda x: x >= threshold, a))

Vấn đề là điều này tạo ra một danh sách tạm thời, sử dụng bộ lọc có chức năng lambda (chậm).

Vì đây là một hoạt động khá đơn giản, có thể có một hàm numpy thực hiện nó một cách hiệu quả, nhưng tôi không thể tìm thấy nó.

Tôi đã nghĩ rằng một cách khác để đạt được điều này có thể là sắp xếp mảng, tìm chỉ mục của ngưỡng và trả về một lát từ chỉ mục đó trở đi, nhưng ngay cả khi điều này sẽ nhanh hơn đối với các đầu vào nhỏ (và nó sẽ không đáng chú ý dù sao ), rõ ràng là tiệm cận của nó kém hiệu quả hơn khi kích thước đầu vào tăng lên.

Có ý kiến ​​gì không? Cảm ơn!

Cập nhật : Tôi cũng đã thực hiện một số phép đo và phân loại + cắt vẫn nhanh hơn gấp đôi so với bộ lọc python thuần túy khi đầu vào là 100.000.000 mục nhập.

In [321]: r = numpy.random.uniform(0, 1, 100000000)

In [322]: %timeit test1(r) # filter
1 loops, best of 3: 21.3 s per loop

In [323]: %timeit test2(r) # sort and slice
1 loops, best of 3: 11.1 s per loop

In [324]: %timeit test3(r) # boolean indexing
1 loops, best of 3: 1.26 s per loop

2
yeah, nó khá đẹp :-) nó thậm chí còn tính toán tự động bao nhiêu lần lặp cần thực hiện để trung bình các số đo nếu mã mất rất ít thời gian để thực hiện
fortran

5
@yosukesabai - IPython's %timeitsử dụng timeitmô-đun nội trang . Hãy xem nó, là tốt. docs.python.org/library/timeit.html
Joe Kington

Câu trả lời:


112

b = a[a>threshold] điều này nên làm

Tôi đã kiểm tra như sau:

import numpy as np, datetime
# array of zeros and ones interleaved
lrg = np.arange(2).reshape((2,-1)).repeat(1000000,-1).flatten()

t0 = datetime.datetime.now()
flt = lrg[lrg==0]
print datetime.datetime.now() - t0

t0 = datetime.datetime.now()
flt = np.array(filter(lambda x:x==0, lrg))
print datetime.datetime.now() - t0

tôi đã nhận

$ python test.py
0:00:00.028000
0:00:02.461000

http://docs.scipy.org/doc/numpy/user/basics.indexing.html#boolean-or-mask-index-arrays


1
thêm kết quả thử nghiệm, không chỉ là những gì tôi nghĩ rằng nó nên làm. : p
yosukesabai

3
Loại lập chỉ mục này không duy trì kích thước của mảng, làm thế nào có thể giữ nguyên số lượng phần tử và bằng không các giá trị ngưỡng phụ?
linello

9
@linello, một [a <= ngưỡng] = 0 sẽ để mặt nạ ra phần mà không vượt quá ngưỡng
yosukesabai

4
Tôi đã gặp phải vấn đề lọc dựa trên hai tiêu chí. Dưới đây là giải pháp: stackoverflow.com/a/3248599/1373468
Robin Newhouse

@yosukesabai Có thể thực hiện chính xác điều này mà không thực sự thay đổi các giá trị ban đầu. Nếu np.macó ý định làm điều đó, tôi không thể tìm ra cách.
embert
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.