2016-12-28 84 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')