2012-06-18 47 views
7

意味着我必須在純Python計算平均車速的算法:NumPy的與條件

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 

有什麼方法重寫與numpy的這個功能呢?

回答

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

我知道你想要一個numpy的解決方案,所以這不符合該標準(@ eumiro的早期的崗位肯定不會),但只是作爲一種替代,這裏至少是一個優化的Python版本,令人驚訝的(我)竟然相當快!

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

在速度方面比較這與numpy(或原始)實現可能會有趣。

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 

其中

speed = range(10000) 

我本來以爲numpy將有這裏邊..任何人都知道爲什麼落後?

更新:

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 

還是不相信這numpy這個特定問題的好工具,除非有一個巨大的速度:)

numpy如何處理內存?列表理解在某些時候會遇到一些限制。

+0

嘗試較大的數字。在1000的情況下,從列表到數組的轉換主導着時間。 –

+0

@JoeKington只是現在這樣做.. :) – Levon

+2

請記住,大列表轉換爲numpy數組是一個相對緩慢的過程。如果數據已經是一個numpy數組(它使用_far_少於列表的內存),那麼numpy版本會更快。否則,對於單個操作,您將看不到大的差異,因爲大部分時間都將被用於將列表轉換爲數組。 –

16

功能numpy.average可以接收weights參數,在這裏可以把從施加於陣列本身的一些條件下產生一個布爾陣列 - 在這種情況下,元素大於0:

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

希望這幫助

+4

+1,這個「權重」提示太棒了! – eumiro

+0

這個解決方案非常好,謝謝。 –

9

我很驚訝沒有人提出最短的解決方案:

speeds_np = np.array(speeds) 

speeds_np[speeds_np>0].mean() 

說明:

speedsNp > 0創建一個滿足等於(in)的相同大小的布爾數組。如果輸入speedsNp,則只產生speedNp的相應值,其中布爾數組的值爲True。所有你需要做的是,只需要結果mean()

+1

這絕對是這裏最好的答案。謝謝@TimY – mjp