2014-04-04 99 views
0

全部,如何優化Python代碼

我打算使用下面的python代碼計算一些特徵值。但是,由於輸入尺寸太大,所以非常耗時。請幫我優化代碼。

leaving_volume=len([x for x in pickup_ids if x not in dropoff_ids]) 
    arriving_volume=len([x for x in dropoff_ids if x not in pickup_ids]) 
    transition_volume=len([x for x in dropoff_ids if x in pickup_ids]) 

    union_ids=list(set(pickup_ids + dropoff_ids)) 
    busstop_ids=[x for x in union_ids if self.geoitems[x].fare>0] 
    busstop_density=np.sum([Util.Geodist(self.geoitems[x].orilat, self.geoitems[x].orilng, self.geoitems[x].destlat, self.geoitems[x].destlng)/(1000*self.geoitems[x].fare) for x in busstop_ids])/len(busstop_ids) if len(busstop_ids) > 0 else 0 
    busstop_ids=[x for x in union_ids if self.geoitems[x].balance>0] 
    smartcard_balance=np.sum([self.geoitems[x].balance for x in busstop_ids])/len(busstop_ids) if len(busstop_ids) > 0 else 0 

嗨,所有,

這裏是我的修訂版本。我在我的GPS跟蹤數據上運行此代碼。它更快。

intersect_ids=set(pickup_ids).intersection(set(dropoff_ids)) 
union_ids=list(set(pickup_ids + dropoff_ids)) 
leaving_ids=set(pickup_ids)-intersect_ids 
leaving_volume=len(leaving_ids) 
arriving_ids=set(dropoff_ids)-intersect_ids 
arriving_volume=len(arriving_ids) 
transition_volume=len(intersect_ids) 

busstop_density=np.mean([Util.Geodist(self.geoitems[x].orilat, self.geoitems[x].orilng, self.geoitems[x].destlat, self.geoitems[x].destlng)/(1000*self.geoitems[x].fare) for x in union_ids if self.geoitems[x].fare>0]) 
if not busstop_density > 0: 
    busstop_density = 0 
smartcard_balance=np.mean([self.geoitems[x].balance for x in union_ids if self.geoitems[x].balance>0]) 
if not smartcard_balance > 0: 
    smartcard_balance = 0 

非常感謝您的幫助。

+0

我不確定np.sum是否可以在列表上工作。此外,在Python 2.7及更低版本中,您使用整數除法(我不知道您的實際版本的Python)。你的前三個表達式是兩個集合差異和一個集合交集使用。在循環中做任何事情都不是很有效率。嘗試使用數組或記錄數組的字典,而不是對象列表(地理項目)。 – Martin

回答

3

只是幾件事情,我注意到,一些Python的效率瑣事:

if x not in dropoff_ids 

使用in運營商檢查的成員是在setlist更有效。但通過listfor迭代可能比set效率更高。所以,如果你希望你的前兩行儘可能高效,那麼你應該事先有兩種類型的數據結構。

list(set(pickup_ids + dropoff_ids)) 

你把數據之前,而不是創建一個長list並從中構建set這是更有效的創建集。幸運的是,您現在可能已經擁有set版本了(請參閱第一條評論)!

首先,你需要問自己一個問題:

是什麼時候救通過構建額外的數據結構的價值它需要構建他們的時間?

下一個:

np.sum([...]) 

我已經被訓練用Python來思考構建list,然後應用在理論上只需要一臺發電機作爲code smell的函數。我不確定這是否適用於numpy,因爲從我記得的事情來看,從一個生成器中提取數據並將其放置在一個numpy結構中並非完全簡單。

看起來這只是代碼的一小部分。如果你真的關心效率問題,我建議使用numpy數組而不是列表,並儘可能地使用numpy的內置數據結構和函數。與內置的Python函數相比,它們可能針對C語言中的原始數據進行更高度的優化。

如果你真的,真的關心效率,那麼你或許應該這樣做數據分析直線上升的C.特別是如果你沒有太多的代碼比你在這裏提出它可能很容易翻譯。

0

我只能支持在他這篇文章中寫過什麼機器。如果您想切換到numpy的,所以如果你的變量pickup_ids和dropoff_ids是numpy的陣列(其中也許他們已經是別人做的事:

dropoff_ids = np.array(dropoff_ids, dtype='i') 
pickup_ids = np.array(pickup_ids, dtype='i') 

,那麼你可以使用的功能np.in1d(),這將給你真/假數組,你可以求和得到真正的條目總數

leaving_volume = (-np.in1d(pickup_ids, dropoff_ids)).sum() 
transition_volume= np.in1d(dropoff_ids, pickup_ids).sum() 
arriving_volume = (-np.in1d(dropoff_ids, pickup_ids)).sum() 

不知何故,我有transition_volume = LEN的感覺(pickup_ids) - arriving_volume但我不是100%確定

另一個函數th在你可能對你有用的是np.unique(),如果你想擺脫重複的條目,以某種方式將你的數組變成一個集合。