2015-06-04 29 views
0

我剛剛開始使用Cython,並希望瞭解如何處理此過程的一些指示。我已經確定了代碼中的速度瓶頸,並希望優化特定操作的性能。Cythonizing應用於熊貓的字符串數組比較函數DataFrame

我有一個熊貓據幀trades,看起來像這樣:

       Codes Price Size 
Time 
2015-02-24 15:30:01-05:00  R6,IS 11.6100 100 
2015-02-24 15:30:01-05:00  R6,IS 11.6100 100 
2015-02-24 15:30:01-05:00  R6,IS 11.6100 100 
2015-02-24 15:30:01-05:00   11.6100 375 
2015-02-24 15:30:01-05:00  R6,IS 11.6100 100 
...        ...  ... ... 
2015-02-24 15:59:55-05:00  R6,IS 11.5850 100 
2015-02-24 15:59:55-05:00  R6,IS 11.5800 200 
2015-02-24 15:59:55-05:00   T 11.5850 100 
2015-02-24 15:59:56-05:00  R6,IS 11.5800 175 
2015-02-24 15:59:56-05:00  R6,IS 11.5800 225 

[5187 rows x 3 columns] 

我有一個numpy陣列叫codes

array(['4', 'AP', 'CM', 'BP', 'FA', 'FI', 'NC', 'ND', 'NI', 'NO', 'PT', 
     'PV', 'PX', 'SD', 'WO'], 
     dtype='|S2') 

我需要過濾trades這樣,如果任何一個值,在codes包含在trades['Codes']中,該行被排除。目前我正在這樣做:

ix = trades.Codes.str.split(',').apply(lambda cs: not any(c in excludes for c in cs)) 
trades = trades[ix] 

但是,這太慢了,我需要加快速度。我想用用Cython(如描述here也許numba,好像用Cython是更好的選擇

基本上,我需要這樣的功能:cythonizing當

def isinCodes(codes_array1, codes_array2): 

    for x in codes_array1: 
     for y in codes_array2: 
      if x == y: return True 

    return False 

做什麼類型的,我需要使用?

+0

爲什麼不使用set.intersection? –

+0

你的算法是二次的,cython不會幫助那麼多 –

回答

2

這是很容易量化的。

構建一個框架,我把10萬*你的榜樣,1M行。

In [76]: df2.info() 
<class 'pandas.core.frame.DataFrame'> 
Int64Index: 1000000 entries, 0 to 9 
Data columns (total 4 columns): 
date  1000000 non-null datetime64[ns] 
code  900000 non-null object 
price  1000000 non-null float64 
volume 1000000 non-null int64 
dtypes: datetime64[ns](1), float64(1), int64(1), object(1) 
memory usage: 38.1+ MB 

In [77]: df2.head() 
Out[77]: 
       date code price volume 
0 2015-02-24 20:30:01 R6,IS 11.61  100 
1 2015-02-24 20:30:01 R6,IS 11.61  100 
2 2015-02-24 20:30:01 R6,IS 11.61  100 
3 2015-02-24 20:30:01 NaN 11.61  375 
4 2015-02-24 20:30:01 R6,IS 11.61  100 

此代碼實際上是:df2.code.str.split(',',expand=True),但是有一個性能問題ATM,將被固定爲0.16.2,請參閱here。所以這段代碼是以非常高效的方式進行分裂的。

In [78]: result = DataFrame([ [ s ] if not isinstance(s, list) else s for s in df2.code.str.split(',') ],columns=['A','B']) 

In [79]: %timeit DataFrame([ [ s ] if not isinstance(s, list) else s for s in df2.code.str.split(',') ],columns=['A','B']) 
1 loops, best of 3: 941 ms per loop 

In [80]: result.head() 
Out[80]: 
    A  B 
0 R6 IS 
1 R6 IS 
2 R6 IS 
3 NaN None 
4 R6 IS 

我加了 'T' 的ISIN結束

In [81]: isin      
Out[81]: 
['4', 
'AP', 
'CM', 
'BP', 
'FA', 
'FI', 
'NC', 
'ND', 
'NI', 
'NO', 
'PT', 
'PV', 
'PX', 
'SD', 
'WO', 
'T'] 

結果

In [82]: df2[(result.A.isin(isin) | result.A.isin(isin))].info() 
<class 'pandas.core.frame.DataFrame'> 
Int64Index: 100000 entries, 7 to 7 
Data columns (total 4 columns): 
date  100000 non-null datetime64[ns] 
code  100000 non-null object 
price  100000 non-null float64 
volume 100000 non-null int64 
dtypes: datetime64[ns](1), float64(1), int64(1), object(1) 
memory usage: 3.8+ MB 

In [83]: df2[(result.A.isin(isin) | result.A.isin(isin))].head() 
Out[83]: 
       date code price volume 
7 2015-02-24 20:59:55 T 11.585  100 
7 2015-02-24 20:59:55 T 11.585  100 
7 2015-02-24 20:59:55 T 11.585  100 
7 2015-02-24 20:59:55 T 11.585  100 
7 2015-02-24 20:59:55 T 11.585  100 

實際操作速度遠遠超過了拆分到這裏。

In [84]: %timeit df2[(result.A.isin(isin) | result.A.isin(isin))]  
10 loops, best of 3: 106 ms per loop