我有四个长度相同的列表:
a=[a1,a2,a3,...,an]
b=[b1,b2,b3,...,bn]
c=[c1,c2,c3,...,cn]
d=[d1,d2,d3,...,dn]
我想做的是:
lengh=len(a)
s=[]
for i in range(0,lengh):
if a[i]>b[i] and a[i]>c[i]:
s.append(a[i]+0.5*b[i]+0.25*d[i])
elif b[i]>a[i] and b[i]>c[i]:
s.append(b[i]+0.5*a[i]+0.25*d[i])
else:
s.append(c[i]+0.25*d[i])
这很有用,但是len(a)>30000000
并且它太慢了。我该怎么做才能加快这段代码的速度?
答案 0 :(得分:1)
使用for
循环是非常低效的,使用numpy列表同样是糟糕的形式。
对我来说,答案取决于使用numpy.choose()
,它将采用一个索引数组(基于上面if
语句的哪一部分适用于给定索引将为0,1,2)以及一系列numpy数组,您可以在其中计算上面的每个if
计算。
因此,假设您将列表转换为numpy数组,例如:
choice1 = a+0.5*b+0.25*d
choice2 = b+0.5*a+0.25*d
choice3 = c+0.25*d
然后,
opt1 = np.greater(a,np.max(b,c))*1
opt2 = np.greater(b,np.max(a,c))*2
opt3 = np.greater(c,np.max(a,b))*3
ind = np.max(opt1,np.max(opt2,opt3))-1
s = np.choose(ind,choice1,choice2,choice3)
Numpy正在快速处理数组,所以虽然这看起来像是浪费了大量精力,但你却避免了for
循环开销,这对于大型数组来说将是一个巨大的胜利。
答案 1 :(得分:0)
您的问题标有 numpy 和 pandas ,即使您只有Python列表。所以你暗示如何加快速度。
import numpy as np
import numexpr as ne
# function that takes Numpy arrays
def compute_result(a, b, c, d):
s1 = ne.evaluate('a + 0.5*b + 0.25*d')
s2 = ne.evaluate('b + 0.5*a + 0.25*d')
s3 = ne.evaluate('c + 0.25*d')
s = np.where((a>b)&(a>c), s1, np.where((b>a)&(b>c), s2, s3))
return s
现在检查一下表现:
length = 30000000
a = np.random.rand(length)
b = np.random.rand(length)
c = np.random.rand(length)
d = np.random.rand(length)
然后在iPython中:
In [35]: %timeit compute_result(a, b, c, d)
1 loops, best of 3: 2.31 s per loop