2016-12-28 113 views
2
ID outcome Source_doc 
23145 A ARR 
23145 A CRE 
23145 B ARR 
23145 C CRE 
23456 B ARR 
23456 B CRE 

來自ARR的ID#145具有[A,B]結果。來自CRE的ID#145具有[A,C]結果。下面你可以看到我會把ID#145放在'not_same_list'中。我的數據集包括445,000行。我執行的過程每100行需要21秒。所以這將花費7個小時!熊貓搜索速度/性能/效率

這個循環最慢的部分是什麼?

我是否最有效地執行Pandas搜索?

Iterrows()會更快嗎?

編輯:關於預期輸出的好點。我其實只是期待一個ID列表。如果AAR_list和CRE_list不相同,我想標記該ID並將其放入一個列表(not_same_list)。所以我在尋找[145,178,...,989,(任何ID其中的成果,不要將其之間不匹配的源文件)

not_same_list = [] 
total_search_start_time = time.time() 
tick = 0 
for IDs in uniq_IDs['ID'].unique(): 
    #Isolate rows by their ID and source doc 
    sco_ARR = uniq_IDs['outcome'][uniq_IDs['ID'] == IDs][uniq_IDs['Source_Doc'] == 'ARR'] 
    sco_CRE = uniq_IDs['outcome'][uniq_IDs['ID'] == IDs][uniq_IDs['Source_Doc'] == 'CRE'] 
    #Remove duplicates 
    ARR_list = set(sco_ARR.values.tolist()) 
    CRE_list = set(sco_CRE.values.tolist()) 

#Check to see if outcomes match between source docs 
if ARR_list != CHRI_list: 
    not_same_list.append(IDs)  

if str(tick)[-2:] == '00': 
    print ('The last {} rows have taken {} seconds...'.format(tick,round(time.time()-total_search_start_time,2))) 
    tick += 1 
else: 
    tick += 1 

print ('The last {} rows have taken {} seconds...'.format(tick,round(time.time()-total_search_start_time,2))) 
print (not_same_list) 

如果任何人都可以做出更好的表,這個問題請這樣做:

+0

我懷疑'drop_duplicates'方法會有所幫助。 – 2016-12-28 17:42:20

+0

你是否也可以放下預期的產出? – Zero

+0

除了傑克馬尼的建議,我認爲熊貓代碼中的一個常見危險標誌是使用'for'循環。把它作爲矢量/矩陣運算通常會加快速度。 – Paul

回答

4

一個大熊貓改寫你的循環將是慣用的方式:

(df.groupby(['ID', 'Source_doc'])['outcome'].apply(set) 
    .groupby(level=0).nunique()[lambda x: x==2].index) 

# Int64Index([23145], dtype='int64', name='ID') 

的原因,您的for循環很慢,因爲你正在處理無序數據,那就是你將數據框子集ID,然後用Source_doc子集,以這種方式你可以用矢量掃描的方式多次遍歷數據幀(取決於你有多少唯一ID和Source_doc);使用groupby()避免了這個問題,因爲它通過組變量對數據幀進行排序,然後通過塊處理塊;

要查看更多關於此理念的信息,請查看this answer

+0

感謝您的澄清。我會試試這個,比較一下時間。 –

+0

這實際上已經完成,所以我的頭在旋轉。我只是驗證結果。從7小時到5分鐘將是驚人的。這有意義嗎? –

+0

如果你有很多'IDs',這是有道理的,ID的數量決定了你的for循環必須經歷整個數據框和子集的次數,這可能非常耗時。 – Psidom

2

我會嘗試這樣的事情

d1 = df.groupby(['ID', 'Source_doc']).outcome.apply(set).unstack() 
print(d1) 

Source_doc  ARR  CRE 
ID       
23145  {B, A} {A, C} 
23456   {B}  {B} 

然後檢查是否等於

d1.ARR == d1.CRE 

ID 
23145 False 
23456  True 
dtype: bool 

可以過濾d1的指數獲得的not_equalID列表的

d1.index[d1.ARR != d1.CRE] 

Int64Index([23145], dtype='int64', name='ID')