Pandas 搜索速度/性能/效率
Posted
技术标签:
【中文标题】Pandas 搜索速度/性能/效率【英文标题】:Pandas search speed/performance/efficiency 【发布时间】:2017-05-13 00:48:26 【问题描述】: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)
如果有人可以为这个问题制作一个更好的表格,请这样做:
【问题讨论】:
我怀疑drop_duplicates
方法会有所帮助。
你能不能也放下预期的输出?
除了 Jack Maney 的建议之外,我认为 pandas 代码中的一般危险信号是使用 for
循环。将其组合为向量/矩阵运算通常会加快速度。
实际上,格式关闭了吗?在我看来,你在这里的 for 循环只是一遍又一遍地设置,而不是使用 ARR_list
和 CRE_list
。我同意 John Galt 的观点,您应该提供预期的输出,以便更清楚您想要做什么。
【参考方案1】:
我会尝试这样的事情
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')
【讨论】:
【参考方案2】:重写 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 循环很慢的原因是因为你正在处理 unsorted 数据,也就是说你用ID
子集你的数据帧,然后用Source_doc
子集你去以矢量扫描方式多次通过数据帧(取决于您拥有多少唯一 ID 和 Source_doc);使用groupby()
避免了这个问题,因为它通过组变量对数据帧进行排序,然后逐块处理;
要了解有关此理念的更多信息,请查看this answer。
【讨论】:
感谢您的澄清。我要试试这个并比较时间。 这实际上已经完成了,所以我头晕目眩。我只是在验证结果。从 7 小时缩短到 5 分钟真是太棒了。这有意义吗? 如果你有很多IDs
,这是有道理的,ID 的数量决定了你的 for 循环必须遍历整个数据帧并将其子集的次数,这可能非常耗时消费。
太好了,看来要退房了。谢谢!以上是关于Pandas 搜索速度/性能/效率的主要内容,如果未能解决你的问题,请参考以下文章
使用 pandas 解析大量日期 - 可扩展性 - 性能下降速度比线性快
为啥我的 Spark 运行速度比纯 Python 慢?性能比较
android--性能优化1--首屏优化&启动速度与执行效率检测
Python Pandas 遍历DataFrame的正确姿势 速度提升一万倍