我有这两个数组:
import numpy as np
a = np.array([0, 10, 20])
b = np.array([20, 30, 40, 50])
我想以下列方式添加两者:
for i in range (len(a)):
for j in range(len(b)):
c = a[i] + b[j]
d = delta(c, dr)
正如您在每次迭代中看到的那样,我得到一个值c
,我通过函数delta
(请参阅帖子末尾的注释)。
问题是,当阵列很大时,我想避免缓慢的Python“for”循环。
我能做的一件事是:
c = np.ravel(a(-1, 1) + b)
哪个更快。问题是现在c
是一个数组,我不得不再使用for循环抛出它。
所以,你对我如何在不使用for循环的情况下做到这一点有任何想法。
注意:delta
是我通过以下方式定义的函数:
def delta(r,dr):
if r >= 0.5*dr and r <= 1.5*dr:
delta = (5-3*abs(r)/dr-np.sqrt(-3*(1-abs(r)/dr)**2+1))/(6*dr)
elif r <= 0.5*dr:
delta = (1+np.sqrt(-3*(r/dr)**2+1))/(3*dr)
else:
delta = 0
return delta
答案 0 :(得分:3)
使用ravel
是一个好主意。请注意,您还可以使用简单的array broadcasting(a[:, np.newaxis] + b[np.newaxis, :]
)。
对于您的function
,您可以对此进行大量改进,因为它仅由三个特定情况组成。可能最好的方法是对这三个部分中的每个部分使用掩蔽。
您从以下开始:
def delta(r,dr):
if r >= 0.5*dr and r <= 1.5*dr:
delta = (5-3*abs(r)/dr-np.sqrt(-3*(1-abs(r)/dr)**2+1))/(6*dr)
elif r <= 0.5*dr:
delta = (1+np.sqrt(-3*(r/dr)**2+1))/(3*dr)
else:
delta = 0
一种常见的替代方法是:
def delta(r, dr):
res = np.zeros_like(r)
ma = (r >= 0.5*dr) & (r <= 1.5*dr) # Create first mask
res[ma] = (5-3*np.abs(r[ma])/dr[ma]-np.sqrt(-3*(1-np.abs(r[ma])/dr[ma])**2+1))/(6*dr[ma])
ma = (r <= 0.5*dr) # Create second mask
res[ma] = (1+np.sqrt(-3*(r[ma]/dr[ma])**2+1))/(3*dr[ma])
return res
初始化为零会处理最终else
个案。我还假设np.abs
比abs
更快---但我确实不确定......
编辑 稀疏矩阵
应该应用相同的基本思想,但也许不使用布尔掩蔽数组,使用有效索引本身会更好......例如类似的东西:
res = scipy.sparse.coo_matrix(np.shape(r))
ma = np.where((r >= 0.5*dr) & (r <= 1.5*dr)) # Create first mask
res[ma] = ...
答案 1 :(得分:0)
这与DilithiumMatrix的答案相同,但使用numpy接受的逻辑函数来生成蒙版。
import numpy as np
def delta(r, dr):
res = np.zeros(r.shape)
mask1 = (r >= 0.5*dr) & (r <= 1.5*dr)
res[mask1] = \
(5-3*np.abs(r[mask1])/dr \
- np.sqrt(-3*(1-np.abs(r[mask1])/dr)**2+1)) \
/(6*dr)
mask2 = np.logical_not(mask1) & (r <= 0.5*dr)
res[mask2] = (1+np.sqrt(-3*(r[mask2]/dr)**2+1))/(3*dr)
return res
答案 2 :(得分:-1)
假设你的两个数组(a和b)不是很大,你可以这样做:
import itertools
a = numpy.array([1,2,3])
b = numpy.array([4,5,6])
c = numpy.sum(list(itertools.product(a, b), 1)
def func(x, y):
return x*y
numpy.vectorize(func)(c, 10)
请注意,对于大型数组,这根本不起作用 - n**2
中有c
个元素,这意味着即使对于看似很小的数组,也会使用巨大的数组记忆量。对于每个100,000个元素的2个阵列,所需的总内存将在74 GB范围内。