将函数数组应用于矩阵列的最快速的方法

时间:2018-09-04 13:10:03

标签: python numpy

我有一个形状为(n,)的函数数组和一个形状为(m, n)的numpy矩阵。现在,我想将每个函数应用于矩阵中的相应列,即

matrix[:, i] = funcs[i](matrix[:, i])

我可以使用for循环(请参见下面的示例)来执行此操作,但是通常不建议在numpy中使用for循环。我的问题是最快(最好是最优雅)的方法是什么?

一个可行的例子

import numpy as np

# Example of functions to apply to each row
funcs  = np.array([np.vectorize(lambda x: x+1),
                   np.vectorize(lambda x: x-2),
                   np.vectorize(lambda x: x+3)])
# Initialise dummy matrix
matrix = np.random.rand(50, 3)

# Apply each function to each column
for i in range(funcs.shape[0]):
    matrix[:, i] = funcs[i](matrix[:, i])

2 个答案:

答案 0 :(得分:1)

对于具有许多行和几列的数组,简单的列迭代应该是时间有效的:

In [783]: funcs = [lambda x: x+1, lambda x: x+2, lambda x: x+3]
In [784]: arr = np.arange(12).reshape(4,3)
In [785]: for i in range(3):
     ...:     arr[:,i] = funcs[i](arr[:,i])
     ...:     
In [786]: arr
Out[786]: 
array([[ 1,  3,  5],
       [ 4,  6,  8],
       [ 7,  9, 11],
       [10, 12, 14]])

如果函数使用一维数组输入,则不需要np.vectorizenp.vectorize通常比普通迭代要慢。)此外,对于这样的迭代,也不需要包装函数列表在一个数组中。遍历列表更快。

索引迭代的变体:

In [787]: for f, col in zip(funcs, arr.T):
     ...:     col[:] = f(col)
     ...:     
In [788]: arr
Out[788]: 
array([[ 2,  5,  8],
       [ 5,  8, 11],
       [ 8, 11, 14],
       [11, 14, 17]])

我在这里使用arr.T,因此迭代位于arr的列上,而不是行上。

一般性观察:在复杂任务上进行几次迭代是非常好的numpy风格。简单任务的许多迭代速度很慢,因此应尽可能在已编译的代码中执行。

答案 1 :(得分:1)

这里的循环很有效,因为循环中的工作很繁重。

可读的解决方案就是:

np.vectorize(apply)(funcs,matrix)