一次在两个ndarrays的相应行上应用一个函数(没有for循环)

时间:2016-04-10 16:22:18

标签: python numpy

我想在不使用for循环的情况下立即将一个函数应用于两个ndarray的相应元素。假设我有以下两个ndarrays xy以及一个函数foo,它接收两个1d数组并计算beta。 我想要的最终结果是计算beta00 = foo(x[0, 0],y[0])beta01 = foo(x[0, 1], y[1])beta10 = foo(x[1, 0],y[0])beta11 = foo(x[1, 1], y[1])并产生预期的结果

   [[beta00, beta01],
    [beta10, beta11]]

我一直在研究vectorize函数和应用函数,但仍然没有解决方案。有人可以帮我吗?非常感谢提前。

import numpy as np
x = np.array([[[0, 1, 2, 3], [0, 1, 2, 3]],
              [[2,3,4,5], [2,3,4,5]]])
y = np.array([[-1, 0.2, 0.9, 2.1], [-1, 0.2, 0.9, 2.1]])

def foo(x,y):
    A = np.vstack([x, np.ones(x.shape)]).T
    return np.linalg.lstsq(A, y)[0][0]

1 个答案:

答案 0 :(得分:1)

所以你想要

beta[i,j] = foo(x[i,j,:], y[j,:])

foo占用2个1d数组,并返回标量。显式:表明我们正在使用3和2数组。

np.vectorize无济于事,因为它的功能必须接受标量,而不是数组。并且 - 它不是速度解决方案。这也是启用广播,处理各种维度的输入的好方法。

有像apply_along(over)_axis这样的循环包装器,但它们仍然是Python级循环。任何实际加速的关键都是重新处理foo,因此它可以在2或3d阵列上运行,而不仅仅是1d阵列。但这可能比它的价值更大,甚至不可能。

因此,作为参考,任何替代方案必须匹配:

beta = np.zeros(x.shape[:2])
for i in range(x.shape[0]):
    for j in range(x.shape[1]):
        beta[i,j] = foo(x[i,j,:],y[j,:])

生成多维索引的另一种方法是:

for i,j in np.ndindex(x.shape[:2]):
    beta[i,j] = foo(x[i,j,:], y[j,:])

但这不是节省时间。

查看是否可以编写foo来接受2d y

  foo(x[i,j,:], y[None,j,:])

最终能够做到:

  beta = foo1(x, y[None,:])