将一个数组的每个元素乘以另一个数组的每个元素

dbl*_*iss 5 python arrays numpy vectorization cartesian-product

假设我有两个数组,

import numpy as np


x = np.array([1, 2, 3, 4])
y = np.array([5, 6, 7, 8])
Run Code Online (Sandbox Code Playgroud)

获取新数组 的最快、最 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
Run Code Online (Sandbox Code Playgroud)

运行上面的代码可以看出,z在这个例子中是

In [3]: z
Out[3]: 
array([  5.,   6.,   7.,   8.,  10.,  12.,  14.,  16.,  15.,  18.,  21.,
        24.,  20.,  24.,  28.,  32.])
Run Code Online (Sandbox Code Playgroud)

Bil*_*kil 5

好吧,我对 numpy 没有太多经验,但是快速搜索给了我这个: 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]])
Run Code Online (Sandbox Code Playgroud)

然后,您可以展平该数组以获得与您请求的相同的输出: http://docs.scipy.org/doc/numpy/reference/ generated/numpy.ndarray.flatten.html

编辑:@Divakar 的回答告诉我们,ravel 会做与 flatten 相同的事情,除了更快的 oO 所以请使用它。

所以在你的情况下,它看起来像这样:

>>> np.multiply.outer(x, y).ravel()
Run Code Online (Sandbox Code Playgroud)

奖励:你可以用这个进入多维度!


Div*_*kar 3

这里可以建议另外两种方法。

使用matrix-multiplication with np.dot

np.dot(x[:,None],y[None]).ravel()
Run Code Online (Sandbox Code Playgroud)

np.einsum

np.einsum('i,j->ij',x,y).ravel()
Run Code Online (Sandbox Code Playgroud)

运行时测试

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
Run Code Online (Sandbox Code Playgroud)

相同,@BilalAkil's answer但用ravel()而不是作为flatten()更快的替代方案 -

In [34]: %timeit np.multiply.outer(x, y).ravel() 
1 loops, best of 3: 211 ms per loop
Run Code Online (Sandbox Code Playgroud)

@BilalAkil's answer:

In [35]: %timeit np.multiply.outer(x, y).flatten()
1 loops, best of 3: 451 ms per loop
Run Code Online (Sandbox Code Playgroud)

@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
Run Code Online (Sandbox Code Playgroud)