Vectorize python函数

时间:2015-07-21 14:53:46

标签: python numpy vectorization apply

我有一个名为old_func的旧函数,它将两个位置参数xy作为输入。使用元组作为输入,函数的输入就是这样写的:

def old_func(position):

    x, y = position 
    return x**2 + y**2

我现在想要一种通过值网格调用函数的快捷方法:

xx = numpy.linspace(0, 1, 100)
yy = numpy.linspace(0, 1, 100)
X, Y = numpy.meshgrid(xx, yy)

array_positions = (X,Y)
old_fun(array_positions)

意图是函数中x上的每个操作都在X上完成,y相同。我尝试使用numpy.vectorize对函数进行矢量化,但这不起作用。我不想更改接受NumPy数组的函数,因为这需要太长时间。

2 个答案:

答案 0 :(得分:5)

您自己的代码应该(并且确实)正常工作:

def old_fun(position):

    x, y = position 
    z = x**2 + y**2
    return z

xx = numpy.linspace(0,1,100)
yy = numpy.linspace(0,1,100)
X,Y = numpy.meshgrid(xx, yy)

array_positions = (X,Y)
Z = old_fun(array_positions)

Z.shape现在是(100, 100)

通常,numpy数组可以与任何标准运算符一起使用,例如+**。请注意,虽然您的old_fun将元组作为输入,并且此元组需要包含两个值,但只要此类型支持数学运算符,这两个值的类型可以是任何值。标准Python标量和numpy数组都支持这些,所以代码工作正常。

关于@ JuanManuel回答的说明:尽管它的效果非常好,apply_along_axis特别是并不意味着矢量化,因为人们通常想要使用它,即从numpy中获得良好的表现。 apply_along_axis将导致缓慢的Python循环,而不是像正确矢量化代码那样的快速C循环。您自己的代码使用了正确的矢量化,因此请使用它。

答案 1 :(得分:1)

以下代码可以解决问题,为您省去了创建array_positions

的麻烦

首先,使用ravelXY展平为形状为(10000,)的NumPy数组。

X_flattened = X.ravel()
Y_flattened = Y.ravel()

然后,使用apply_along_axis以这些展平数组的长度迭代地实现自定义函数。

float_array = np.apply_along_axis(old_func, 0, (X_flattened, Y_flattened))

最后,将输出数组重新整形为所需的(100, 100)形状。

np.reshape(float_array, (100, 100))