优化嵌套for循环所需的WRT时间



我有一本字典的字典。我们说'data'和一个numpy数组。我们说"stats"。我想检查是否:-

numpy数组的第一列和第二列存在于我的字典的字典的两个键的范围内,或者如果这两个键存在于我的numpy数组的列的范围内。

提供我的代码供参考主要的问题是这要花很多时间,我非常感谢任何能让它运行得更快的帮助。

任何帮助都将不胜感激,谢谢你

final = []
for x,y,w,h,area in stats[:]:
valid = True
if any([(x in range(s["hpos_start"]-2, s["hpos_end"] + 2) and y in range(s["vpos_start"]-2, s["vpos_end"] + 2)) or ((int(s['hpos_start']) in range(x,x+w) and int(s['vpos_start']) in range(y,y+h))) for _, s in data.items()]):
valid = False
if valid:
final.append([x,y,w,h])

sample for stats =

[[    246       1102    1678   2214  172182],
[     678       1005    1688   2214  3528850],
[     1031      241     17     23    331]]

sample for data =

{'0': {
'hpos_start': 244,
'hpos_end': 296,
'vpos_start': 1099,
'vpos_end': 3898,
},
'1': {
'hpos_start': 679,
'hpos_end': 952,
'vpos_start': 231,
'vpos_end': 281
},
'2': {'hpos_start': 1077,
'hpos_end': 1174,
'vpos_start': 231,
'vpos_end': 281
}}

stats is about size (35,5)数据大小约为212

也可以大于

我的建议是将统计数据和数据转换为numpy数组,然后找出一种方法来实现您的特定过滤,而不需要使用显式for-循环。这就是傻瓜的全部优势!此外,您还可以使用特殊的索引方法来生成final数组,而不是逐个构建它。添加到列表中可能会有点慢…

对于一个小但易于实现的加速:当您在代码中使用anyall时,您应该避免传递list,而可以传递生成器表达式。如果您只是从any内部删除方括号,您应该看到一点加速,因为您将避免总是构建完整的中间列表!any(和all)很酷的一点是,在处理迭代器时,它们有所谓的短路:一旦any找到一个True的项,它知道它可以停止查看其余的项,因为答案将是true。同样,一旦all找到一个False的项目,它将停止查看其余的,只返回False

但实际上,将您的输入转换为numpy数组(或者可能是numpy数组和pandas数据框架),然后尝试找出避免for循环的方法。

为了测试和计时代码,我在for循环中运行了100000次。您的代码运行时间为1.406秒。我建议下面的代码:替换"in range"通过限制测试测试,抑制int(..)类型转换,它在我的pc上运行0.609秒。在你的电脑上试一下,看看你能获得什么速度:

import time
start = time.process_time()
for i in range(100000) :
## 100000x 0.609
final = []
for x,y,h,w,area in stats:
if    any([
((
(s["hpos_start"]-2) <= x and x <= (s["hpos_end"] + 2)
and
((s["vpos_start"]-2)<=y and y <=( s["vpos_end"] + 2))
))
or ((
(x<= s['hpos_start'] <= (x+w))
and
(y<= s['vpos_start'] <=(y+h))
))
for s in data.values()
]):
pass
else:
final.append([x,y,w,h])

print(time.process_time() - start)

最新更新