Numpy自动元素功能

时间:2018-04-11 15:06:30

标签: python numpy elementwise-operations

我有一个关于numpy的问题。

我们假设我有一个功能

def calcSomething(A,t):

    return t*A

我想传递一个常量numpy数组,例如A=np.array([1.0,2.0])和t作为等距点,例如t = np.linspace(0.0,1.0,10)。 现在,当我执行

x = calcSomething(A,t)

我想获得x[0] = [0,0]x[1] = [.1,.2],...,x[9] = [1.0,2.0]。有没有一种简单的方法来实现它,或者我是否必须使用for循环并追加它来实现它?

编辑:'calcSomething():只是一个更复杂功能的占位符。

E.g。 y=np.sin(t)会产生y[i]=np.sin(t[i])。这就是我想要的通用功能。

提前致谢!

3 个答案:

答案 0 :(得分:1)

尽可能使用对整个阵列进行操作的numpy函数和运算符,并为您执行必要的broadcasting

In [24]: A = np.array([1.0,2.0]); t = np.linspace(0.0, 1.0, 10)
In [25]: x = t[:,None] * A[None,:]
In [26]: x.shape
Out[26]: (10, 2)
In [27]: x[:3,:]
Out[27]: 
array([[0.        , 0.        ],
       [0.11111111, 0.22222222],
       [0.22222222, 0.44444444]])
In [28]: np.sin(t)
Out[28]: 
   array([0.        , 0.11088263, 0.22039774, 0.3271947 , 0.42995636,
          0.52741539, 0.6183698 , 0.70169788, 0.77637192, 0.84147098])

如果你有一个仅适用于标量输入的函数,你可以使用np.vectorize从广播数组中提取这些值:

In [30]: def foo(A,t):
    ...:     return t*A
    ...: 
In [31]: f = np.vectorize(foo, otypes=[float])
In [32]: f(A[None,:], t[:,None])
Out[32]: 
array([[0.        , 0.        ],
       [0.11111111, 0.22222222],
       [0.22222222, 0.44444444],
       ....
       [1.        , 2.        ]])

vectorize是一种便利功能;它不承诺速度。将其时间与In[25]

进行比较
In [33]: timeit f(A[None,:], t[:,None])
41.3 µs ± 48.5 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [34]: timeit x = t[:,None] * A[None,:]
5.41 µs ± 8.2 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

慢了8倍。

或使用标量math.sin函数:

In [35]: import math
In [36]: g = np.vectorize(math.sin)
...
In [39]: timeit g(t)
39 µs ± 72.4 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [40]: timeit np.sin(t)
1.4 µs ± 2.72 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

迭代调用math.sinnp.sin快,但给定整个数组时np.sin要快得多。

基本区别在于vectorize,就像显式循环在解释的Python中迭代一样,并为每个输出元素调用一次函数。 np.sin和数组*正在迭代,但是在编译代码中。

在Python和numpy中有各种迭代方法,但它们很少能为你提供超过2倍的加速。

有一些工具可以将计算移动到已编译的代码,例如cythonnumba。搜索这些标签,了解如何使用它们。

答案 1 :(得分:0)

您可以使用矩阵乘法:

>>> A = np.array([1.0,2.0])
>>> t = np.linspace(0.0,1.0,10)
>>> np.matmul(t.reshape(10, 1), A.reshape(1, 2))
array([[0.        , 0.        ],
       [0.11111111, 0.22222222],
       [0.22222222, 0.44444444],
       [0.33333333, 0.66666667],
       [0.44444444, 0.88888889],
       [0.55555556, 1.11111111],
       [0.66666667, 1.33333333],
       [0.77777778, 1.55555556],
       [0.88888889, 1.77777778],
       [1.        , 2.        ]])

答案 2 :(得分:0)

只需使用None指定新轴:

A[None, :] * t[:, None]