将一个数组的每个元素乘以另一个数组的每个元素
Multiplying every element of one array by every element of another array
假设我有两个数组,
import numpy as np
x = np.array([1, 2, 3, 4])
y = np.array([5, 6, 7, 8])
获取新数组z
的最快、最Pythonic 等方法是什么,其中元素数等于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.])
嗯,我对 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]])
然后您可以展平该数组以获得与您请求的相同的输出:
http://docs.scipy.org/doc/numpy/reference/generated/numpy.ndarray.flatten.html
编辑:@Divakar 的回答向我们展示了 ravel 将做与展平相同的事情,除了更快 o.O 所以改用它。
所以在你的情况下,它看起来像这样:
>>> np.multiply.outer(x, y).ravel()
奖金:你可以用这个去多维!
这是一种方法:
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
不过,最好去掉那个计数器,还有 for
循环(但至少我去掉了其中一个循环)。
更新
作为单行本,其他提供的答案比这个更好(根据我的标准,它重视简洁)。下面的计时结果表明@BilalAkil 的答案比@TimLeatart 的更快:
In [10]: %timeit np.array([x * j for j in y]).flatten()
The slowest run took 4.37 times longer than the fastest. This could mean that an intermediate result is being cached
10000 loops, best of 3: 24.2 µs per loop
In [11]: %timeit np.multiply.outer(x, y).flatten()
The slowest run took 5.59 times longer than the fastest. This could mean that an intermediate result is being cached
100000 loops, best of 3: 10.5 µs per loop
方法如下:
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()
这里可以推荐另外两种方法。
使用matrix-multiplication with np.dot
:
np.dot(x[:,None],y[None]).ravel()
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
与 相同,但使用 ravel()
而不是 flatten()
作为更快的替代方案 -
In [34]: %timeit np.multiply.outer(x, y).ravel()
1 loops, best of 3: 211 ms per loop
:
In [35]: %timeit np.multiply.outer(x, y).flatten()
1 loops, best of 3: 451 ms per loop
:
In [36]: %timeit np.array([y * a for a in x]).flatten()
1 loops, best of 3: 766 ms per loop
我知道我来晚了,但我想我会为将来阅读这个问题的任何人献上我的帽子。使用与@Divakar 相同的指标,我将我认为更直观的解决方案添加到列表中(测量的第一个代码片段):
import numpy as np
N = 10000
x = np.random.rand(N)
y = np.random.rand(N)
%timeit np.ravel(x[:,None] * y[None])
635 ms ± 19.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit np.outer(x, y).ravel()
640 ms ± 16 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit np.dot(x[:,None],y[None]).ravel()
853 ms ± 57.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit np.einsum('i,j->ij',x,y).ravel()
754 ms ± 19.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
基于执行时间的相似性,numpy.outer
的功能似乎与我的内部解决方案完全相同,尽管您应该对这样的观察持保留态度。
我觉得它更直观的原因是,与所有其他解决方案不同,它的语法并不严格限于乘法。例如,np.ravel(x[:,None] / y[None])
将为 x 中的每个 a 和 y 中的每个 b 提供 a / b。
假设我有两个数组,
import numpy as np
x = np.array([1, 2, 3, 4])
y = np.array([5, 6, 7, 8])
获取新数组z
的最快、最Pythonic 等方法是什么,其中元素数等于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.])
嗯,我对 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]])
然后您可以展平该数组以获得与您请求的相同的输出: http://docs.scipy.org/doc/numpy/reference/generated/numpy.ndarray.flatten.html
编辑:@Divakar 的回答向我们展示了 ravel 将做与展平相同的事情,除了更快 o.O 所以改用它。
所以在你的情况下,它看起来像这样:
>>> np.multiply.outer(x, y).ravel()
奖金:你可以用这个去多维!
这是一种方法:
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
不过,最好去掉那个计数器,还有 for
循环(但至少我去掉了其中一个循环)。
更新
作为单行本,其他提供的答案比这个更好(根据我的标准,它重视简洁)。下面的计时结果表明@BilalAkil 的答案比@TimLeatart 的更快:
In [10]: %timeit np.array([x * j for j in y]).flatten()
The slowest run took 4.37 times longer than the fastest. This could mean that an intermediate result is being cached
10000 loops, best of 3: 24.2 µs per loop
In [11]: %timeit np.multiply.outer(x, y).flatten()
The slowest run took 5.59 times longer than the fastest. This could mean that an intermediate result is being cached
100000 loops, best of 3: 10.5 µs per loop
方法如下:
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()
这里可以推荐另外两种方法。
使用matrix-multiplication with np.dot
:
np.dot(x[:,None],y[None]).ravel()
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
与 ravel()
而不是 flatten()
作为更快的替代方案 -
In [34]: %timeit np.multiply.outer(x, y).ravel()
1 loops, best of 3: 211 ms per loop
In [35]: %timeit np.multiply.outer(x, y).flatten()
1 loops, best of 3: 451 ms per loop
In [36]: %timeit np.array([y * a for a in x]).flatten()
1 loops, best of 3: 766 ms per loop
我知道我来晚了,但我想我会为将来阅读这个问题的任何人献上我的帽子。使用与@Divakar 相同的指标,我将我认为更直观的解决方案添加到列表中(测量的第一个代码片段):
import numpy as np
N = 10000
x = np.random.rand(N)
y = np.random.rand(N)
%timeit np.ravel(x[:,None] * y[None])
635 ms ± 19.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit np.outer(x, y).ravel()
640 ms ± 16 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit np.dot(x[:,None],y[None]).ravel()
853 ms ± 57.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit np.einsum('i,j->ij',x,y).ravel()
754 ms ± 19.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
基于执行时间的相似性,numpy.outer
的功能似乎与我的内部解决方案完全相同,尽管您应该对这样的观察持保留态度。
我觉得它更直观的原因是,与所有其他解决方案不同,它的语法并不严格限于乘法。例如,np.ravel(x[:,None] / y[None])
将为 x 中的每个 a 和 y 中的每个 b 提供 a / b。