2012-06-18 28 views
7

Tôi có thuật toán tính tốc độ trung bình trong python tinh khiết:NumPy nghĩa với tình trạng

speed = [...] 
    avg_speed = 0.0 
    speed_count = 0 
    for i in speed: 
     if i > 0: # I dont need zeros 
      avg_speed += i 
      speed_count += 1 

    if speed_count == 0: 
     return 0.0 

    return avg_speed/speed_count 

Có cách nào để viết lại chức năng này với NumPy?

Trả lời

9
import numpy as np 

def avg_positive_speed(speed): 
    s = np.array(speed) 
    positives = s > 0 
    if positives.any(): 
     return s[positives].mean() 
    else: 
     return 0. 


speed = [1., 2., 0., 3.] 
print avg_positive_speed(speed) 
# prints 2.0 

print avg_positive_speed([0., 0.]) 
# prints 0.0 
3

Tôi biết bạn muốn có một giải pháp numpy, vì vậy đây không đáp ứng được các tiêu chí (@ bài trước eumiro của chắc chắn không), nhưng cũng giống như một sự thay thế, đây là một phiên bản Python tối ưu mà đáng ngạc nhiên (cho tôi ít nhất) hóa ra khá nhanh chóng!

speeds = [i for i in speed if i > 0] 
return sum(speeds)/(1.0 * len(speeds)) if sum(speeds) > 0 else 0.0 

Có thể thú vị khi so sánh việc này với việc thực hiện gọn gàng (hoặc bản gốc) về tốc độ.

In [14]: timeit original(speed)    # original code 
1000 loops, best of 3: 1.13 ms per loop 

In [15]: timeit python_opt(speed)   # above Python 2 liner 
1000 loops, best of 3: 582 us per loop 

In [16]: timeit avg_positive_speed(speed) # numpy code 
1000 loops, best of 3: 1.2 ms per loop 

nơi

speed = range(10000) 

Tôi đã có thể nghĩ rằng numpy sẽ có chút lợi thế ở đây .. ai biết tại sao nó lại thua?

Cập nhật:

với speed = range(100000):

In [19]: timeit original(speed) 
100 loops, best of 3: 12.2 ms per loop 

In [20]: timeit python_opt(speed) 
100 loops, best of 3: 11 ms per loop 

In [21]: timeit avg_positive_speed(speed) 
100 loops, best of 3: 12.5 ms per loop 

Vẫn không thuyết phục rằng numpy là một công cụ tốt cho vấn đề này đặc biệt, trừ khi có một số lượng khổng lồ tốc độ :)

Bộ nhớ xử lý gọn gàng như thế nào? danh sách hiểu sẽ tại một số điểm bump vào một số hạn chế.

+0

Thử số lớn hơn. Với 1000, việc chuyển đổi từ một danh sách sang một mảng là thống trị thời gian. –

+0

@JoeKington chỉ thực hiện việc này ngay bây giờ .. :) – Levon

+2

Hãy nhớ rằng việc chuyển đổi danh sách lớn sang mảng có nhiều mảng là một quá trình tương đối chậm. Nếu dữ liệu đã là một mảng numpy (sử dụng _far_ ít bộ nhớ hơn một danh sách) thì các phiên bản gọn gàng sẽ nhanh hơn nhiều. Nếu không, bạn sẽ không thấy sự khác biệt lớn đối với một thao tác đơn lẻ, vì phần lớn thời gian sẽ được chuyển lên danh sách chuyển đổi thành một mảng. –

16

Chức năng numpy.average có thể nhận được một cuộc tranh luận weights, nơi bạn có thể đặt một mảng boolean được tạo ra từ một số điều kiện áp dụng cho các mảng chính nó - trong trường hợp này, một yếu tố là lớn hơn 0:

average_speed = numpy.average(speeds, weights=(speeds > 0)) 

Hy vọng điều này giúp

+4

+1, gợi ý 'trọng lượng' này thật tuyệt vời! – eumiro

+0

Giải pháp này là tuyệt vời, cảm ơn bạn. –

9

tôi ngạc nhiên không ai đã gợi ý các giải pháp ngắn nhất:

speeds_np = np.array(speeds) 

speeds_np[speeds_np>0].mean() 

Giải thích:

speedsNp > 0 tạo mảng boolean có cùng kích thước thỏa mãn (bằng) bình đẳng. Nếu được đưa vào speedsNp, nó chỉ mang lại giá trị tương ứng của speedNp trong đó giá trị của mảng boolean là True. Tất cả những gì bạn cần làm sau đó, chỉ cần lấy số mean() của kết quả.

+1

Đây chắc chắn là câu trả lời hay nhất ở đây. Cảm ơn @TimY – mjp

Các vấn đề liên quan