【发布时间】:2021-11-20 07:02:33
【问题描述】:
一段时间以来,我一直试图让我的彗星程序的慢速部分运行得更快。我有一行如下
s1=np.isin(secondsplit,file2new)
secondsplit 是一个 numpy 数组。平均而言,它的大小约为 600 x 600,并且充满了浮动。 file2new 是一个浮点数列表,大小通常为 300-700。
我在堆栈交换论坛上讨论了这个问题,并得到了一个解决方案,它使用列表理解和将 file2new 转换为集合来加快处理速度。 我的小规模测试代码有效,列表理解速度提高了 5 倍。当我扩大规模并将彗星程序更改为以相同方式使用列表时,问题就出现了。随着数据量的增加,这段代码的运行速度会慢 4 倍!
有人建议我应该制作一个大型示例供人们查看我所做的。由于今天帮助论坛上的人不多,所以我现在将其发布在这里。
import numpy as np
import timeit
mylist=[]
for i in range (0,700):
mylist.append(i)
myarray = np.empty((600, 600))
for x in range (0,600):
for y in range (0,600):
p=y+(x*0.25)
myarray[y,x]=p
myarray=np.asarray(myarray)
# object here is to produce an array of 600 x 600 with True/False values depending
# on whether elements in myarray are in mylist.
# The question is - what ia thw fastest way to do so? Note that all array values and
# mylist values are floats. There must be an exact match. One
# can't use isclose because it is slower
# Example 1 - using isin (loop of 10000 used for timing illustration)
starttime = timeit.default_timer()
for i in range (0,10):
s1=np.isin(myarray,mylist)
print (s1[0][0:10])
print (s1[1][0:10])
print (s1[2][0:10])
print("The time difference is :", timeit.default_timer() - starttime)
# Example 2- using list comprehension and conversion of mylist to a set (it runs way
# slower without set conversion)
def quickisin(array,mylist):
mylist=set(mylist)
p=[]
t=len(array)
for j in range (0,t):
h=array[j]
s1 = [item in mylist for item in h]
p.append(s1)
q=np.asarray(p)
return q
starttime = timeit.default_timer()
for i in range (0,10):
s1=quickisin(myarray,mylist)
print (s1[0][0:10])
print (s1[1][0:10])
print (s1[2][0:10])
print("The time difference is :", timeit.default_timer() - starttime)
如您所见,代码的第一部分设置了示例变量。我使用 myarray 和 mylist 让人们更容易理解。 myarray 是 600x 600 数组,mylist 是大小为 700 的列表,所有浮点数。
预期的输出应该是一个与 myarray 大小相同但具有 True 和 False 值的 numpy 数组。每第 4 项为 True。
运行时产生的输出如下。
runfile('C:/A/untitled7.py', wdir='C:/A')
[ True False False False True False False False True False]
[ True False False False True False False False True False]
[ True False False False True False False False True False]
The time difference is : 0.5151480000000674
[ True False False False True False False False True False]
[ True False False False True False False False True False]
[ True False False False True False False False True False]
The time difference is : 2.0399810999999772
我的问题,如果你选择接受它,你的挑战是使用列表推导来使 quickisin 函数比使用 numpy 的 isin 更快。最快的列表理解解决方案的奖品是吹牛。
请注意,数组中的浮点数与列表的匹配必须准确,因此排除了使用 isclose 的可能性。
谢谢你
【问题讨论】:
-
您可以用这样的列表理解替换您的 for 循环:
p = [[item in mylist for item in h] for h in array]但恐怕您可以从中获得很多。在我看来,您的代码中没有太多可以优化的东西,而且列表推导的使用在这里对您没有帮助。
标签: python list performance list-comprehension isin