2016-07-07 61 views
2

我有一個很大的df,我需要改變。對於一個計算,我想在pborderid上對數據進行分組,然後只保留在to_wpadr中具有重複值的行。由於組數太多,熊貓過濾器執行緩慢

這是我的df的一個例子。

 pborderid pbcarid wsid to_wpadr colli pk_end_time    
10 76079450 61838497 hp1 523-369p  1 2016-07-01 00:00:38  
11 76079450 61838504 hp1 523-370p  1 2016-07-01 00:00:47  
12 76079450 61838110 hp1 523-372p  1 2016-07-01 00:01:05  
13 76079450 61838225 hp1 523-372p  2 2016-07-01 00:01:13  
14 76079450 61838504 hp1 523-372p  3 2016-07-01 00:01:30  
15 76079450 61838497 hp1 523-373p  1 2016-07-01 00:01:45  
16 76079450 61838504 hp1 523-377p  1 2016-07-01 00:01:55  
17 76079450 61838110 hp1 523-376p  5 2016-07-01 00:02:26  
18 76079450 61838225 hp1 523-376p  1 2016-07-01 00:02:33  
19 76079450 61838497 hp1 523-376p  6 2016-07-01 00:02:55 

使用以下代碼工作,但是當組數增加時,性能顯着下降,最多需要20秒。我認爲這應該是可行的,只使用pborderid作爲組,然後過濾/應用。

ap=ot.groupby(["pborderid","to_wpadr"],sort=False).filter(lambda x: len(x) >1) 

任何人有任何建議如何我只能使用一個groupcolumn或如何我可以改善其他性能?

這裏是想要的結果:

pborderid pbcarid wsid to_wpadr colli   pk_end_time 
12 76079450 61838110 hp1 523-372p  1 2016-07-01 00:01:05  
13 76079450 61838225 hp1 523-372p  2 2016-07-01 00:01:13   
14 76079450 61838504 hp1 523-372p  3 2016-07-01 00:01:30  
17 76079450 61838110 hp1 523-376p  5 2016-07-01 00:02:26   
18 76079450 61838225 hp1 523-376p  1 2016-07-01 00:02:33   
19 76079450 61838497 hp1 523-376p  6 2016-07-01 00:02:55   

回答

2

我不知道這是否會更快,但你可以嘗試使用DataFrame.duplicated僅在重複進行過濾。

ap = ot[ot.duplicated(subset=['pborderid', 'to_wpadr'], keep=False)] 

定時對1M行DF:

In [244]: df = pd.concat([df] * 10**5, ignore_index=True) 

In [245]: %timeit df.groupby(["pborderid","to_wpadr"],sort=False).filter(lambda x: len(x) >1) 
1 loop, best of 3: 313 ms per loop 

In [246]: %timeit df[df.duplicated(subset=['pborderid', 'to_wpadr'], keep=False)] 
10 loops, best of 3: 129 ms per loop 

In [247]: df.shape 
Out[247]: (1000000, 6) 
+0

我給你的答案添加了時間 - 它幾乎快了2.5倍;) – MaxU

+1

@MaxU:很好地完成了。謝謝! –

0

通過this solution的啓發,我們可以在這種情況下更換groupby操作了。實施將是這個樣子 -

# Create numerical IDs for relevant columns and a combined one 
ID1 = np.unique(df['pborderid'],return_inverse=True)[1] 
ID2 = np.unique(df['to_wpadr'],return_inverse=True)[1] 
ID = np.column_stack((ID1,ID2)) 

# Convert to linear indices 
lidx = np.ravel_multi_index(ID.T,ID.max(0)+1) 

# Get unique IDs for each element based on grouped uniqueness and group counts 
_,ID,count = np.unique(lidx,return_inverse=True,return_counts=True) 

# Look for counts>1 and collect respective IDs and thus respective rows off df 
df_out = df[np.in1d(ID,np.where(count>1)[0])] 

採樣運行 - 在我結束

In [233]: df 
Out[233]: 
    pborderid to_wpadr values 
0  ID0  John  3 
1  ID1 Erick  8 
2  ID1  John  3 
3  ID1 Mandy  5 
4  ID0 Erick  9 
5  ID1 Mandy  4 
6  ID0  John  6 
7  ID1  John  1 

In [234]: df_out 
Out[234]: 
    pborderid to_wpadr values 
0  ID0  John  3 
2  ID1  John  3 
3  ID1 Mandy  5 
5  ID1 Mandy  4 
6  ID0  John  6 
7  ID1  John  1 

運行測試似乎並不建議使用這種方法的任何改進過groupby方法,因爲在其他的解決辦法上市。所以,它看起來像df.groupby將是首選的方式!

+0

謝謝Divakar。我雖然大多數熊貓的功能,如重複已經建立uppon numpy。但仍然好奇你的方法是否會比前一個方法更快,這已經有了很大的改進。你的代碼存在的問題是我應該根據兩列找到唯一的值,這樣2d對象。我在視圖中試過,但熊貓數據框沒有這個屬性。那麼,如何應用您的方法來基於多列來查找唯一行?提前謝謝了! – XsjakieX

+0

@XsjakieX是的,這種方法在其他的「groupby」方法上沒有任何改進。所以,我會說堅持'groupby'。很難擊敗這種內置的!修復了我的代碼以合併基於'groupby'的兩列。 – Divakar