说我有两个数组,
import numpy as np
x = np.array([1, 2, 3, 4])
y = np.array([5, 6, 7, 8])
什么是最快的,最Pythonic的等方式来获得一个新数组z
,其元素数等于x.size * y.size
,其中元素是每对元素(x_i, y_j)
的乘积]从两个输入数组。
换句话说,我正在寻找z
为z[k]
的数组x[i] * y[j]
。
一种简单但效率低下的方法如下:
z = np.empty(x.size * y.size)
counter = 0
for i in x:
for j in y:
z[counter] = i * j
counter += 1
运行上面的代码显示此示例中的z
是
In [3]: z
Out[3]:
array([ 5., 6., 7., 8., 10., 12., 14., 16., 15., 18., 21.,
24., 20., 24., 28., 32.])
这里可以建议另外两种方法。
使用matrix-multiplication with np.dot
:
matrix-multiplication with np.dot
使用np.dot(x[:,None],y[None]).ravel()
:
np.einsum
运行时测试
np.einsum
与np.einsum('i,j->ij',x,y).ravel()
相同,但用In [31]: N = 10000
...: x = np.random.rand(N)
...: y = np.random.rand(N)
...:
In [32]: %timeit np.dot(x[:,None],y[None]).ravel()
1 loops, best of 3: 302 ms per loop
In [33]: %timeit np.einsum('i,j->ij',x,y).ravel()
1 loops, best of 3: 274 ms per loop
代替@BilalAkil's answer
作为更快的替代方法-
@BilalAkil's answer
ravel()
:
flatten()
In [34]: %timeit np.multiply.outer(x, y).ravel()
1 loops, best of 3: 211 ms per loop
:
@BilalAkil's answer
嗯,我对numpy并没有太多的经验,但是通过快速搜索我发现了这一点:@BilalAkil's answer
In [35]: %timeit np.multiply.outer(x, y).flatten()
1 loops, best of 3: 451 ms per loop
然后,您可以展平该数组以获得与您请求相同的输出:@Tim Leathart's answer
编辑:@Divakar的回答告诉我们,拉夫除拉平外会做与拉平相同的操作,所以请改用拉平。
因此,您的情况如下所示:
@Tim Leathart's answer
奖励:您可以用这个去多维!
这是一种实现方法:
In [36]: %timeit np.array([y * a for a in x]).flatten()
1 loops, best of 3: 766 ms per loop
这里是一种方法:
http://docs.scipy.org/doc/numpy/reference/generated/numpy.ufunc.outer.html
不过,最好除掉那个计数器以及>>> np.multiply.outer([1, 2, 3], [4, 5, 6])
array([[ 4, 5, 6],
[ 8, 10, 12],
[12, 15, 18]])
循环(但至少我要摆脱其中一个循环)。
作为一个班轮,其他提供的答案比这个答案更好(根据我的标准,它重视简洁性)。下面的计时结果显示@BilalAkil的答案比@TimLeathart的答案要快:
http://docs.scipy.org/doc/numpy/reference/generated/numpy.ndarray.flatten.html
我知道我在这里参加聚会迟到了,但是我想以后对任何阅读此问题的人都应该戴上帽子。使用与@Divakar相同的度量标准,我在列表中添加了我认为是更直观的解决方案(测得的第一个代码段):
>>> np.multiply.outer(x, y).ravel()
基于执行时间的相似性,import numpy as np
x = np.array([1, 2, 3, 4])
y = np.array([5, 6, 7, 8])
z = np.array([y * a for a in x]).flatten()
的功能似乎与我的内部解决方案完全相同,尽管您应该使用大量盐进行此类观察。
之所以我觉得它更直观,是因为与所有其他解决方案不同,它的语法并不严格限于乘法。例如,import itertools
z = np.empty(x.size * y.size)
counter = 0
for i, j in itertools.product(x, y):
z[counter] = i * j
counter += 1
将为x中的每个a和y中的b提供一个/ b。