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 :(得分:4)
重写你的for循环的pandas惯用方法是:
(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。
答案 1 :(得分: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_equal
ID
的
d1.index[d1.ARR != d1.CRE]
Int64Index([23145], dtype='int64', name='ID')