Python:使用np.apply_沿_轴使用函数返回数组

Python:使用np.apply_沿_轴使用函数返回数组,python,numpy,vectorization,Python,Numpy,Vectorization,我试着做如下的事情 import numpy as np arr = np.array([0,1,2,3]) fn = lambda x: np.array([x/2,x*2]) res = np.apply_along_axis(fn,0,arr) 也就是说,我想使用np.apply_沿_轴和一个返回数组而不是单个值的函数。但是,这会导致以下错误 Traceback (most recent call last): File "<stdin>", line 1, in <

我试着做如下的事情

import numpy as np
arr = np.array([0,1,2,3])
fn = lambda x: np.array([x/2,x*2])
res = np.apply_along_axis(fn,0,arr)
也就是说,我想使用
np.apply_沿_轴
和一个返回数组而不是单个值的函数。但是,这会导致以下错误

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.5/site-packages/numpy/lib/shape_base.py", line 117, in apply_along_axis
    outarr[tuple(i.tolist())] = res
ValueError: could not broadcast input array from shape (2,4) into shape (2)
请注意,我的实际用例比给定的
fn
更复杂。我想知道是否有一种方法通常可以使用
np。使用返回数组的函数沿\u轴应用\u
,或者是否有一种不同的(numpythonic)方法来实现相同的功能


谢谢

我发现的一个解决方法是堆叠结果,使lambda返回一维数组而不是二维数组:

arr = np.array([0, 1, 2, 3])
fn = lambda x: np.hstack([x/2, x*2])
res = np.apply_along_axis(fn, 0, arr)

然后您可以根据需要重塑
res

我发现的一个解决方法是叠加结果,使lambda返回一维数组而不是二维数组:

arr = np.array([0, 1, 2, 3])
fn = lambda x: np.hstack([x/2, x*2])
res = np.apply_along_axis(fn, 0, arr)
然后您可以根据需要重塑
res

这类东西——沿数组应用常规Python函数——基本上与
for
循环相同。它不会很快,即使您使用NumPy函数来调用您的函数。因此,请保持简单:

arr = np.array([0,1,2,3])
fn = lambda x: [x/2,x*2]
res = np.array(list(map(fn, arr)))
或者,如果您关心性能:

arr = np.array([0,1,2,3])
funcs = [lambda x: x/2.0, lambda x: x*2.0]
res = np.empty((len(arr), len(funcs)))
for i, func in enumerate(funcs):
    res[:,i] = func(arr)
第二种方法要快得多,只要数组中的行数大于要应用的函数数。这是因为您只需要循环几次,使用NumPy矢量化代码一次将每个函数应用于整个输入,而不是逐个循环输入行。

这种事情——沿数组应用常规Python函数——基本上与
for
循环相同。它不会很快,即使您使用NumPy函数来调用您的函数。因此,请保持简单:

arr = np.array([0,1,2,3])
fn = lambda x: [x/2,x*2]
res = np.array(list(map(fn, arr)))
或者,如果您关心性能:

arr = np.array([0,1,2,3])
funcs = [lambda x: x/2.0, lambda x: x*2.0]
res = np.empty((len(arr), len(funcs)))
for i, func in enumerate(funcs):
    res[:,i] = func(arr)

第二种方法要快得多,只要数组中的行数大于要应用的函数数。这是因为您只循环了几次,使用NumPy矢量化代码一次将每个函数应用于整个输入,而不是逐个循环输入行。

您的第一个解决方案将生成一个形式为
数组(,dtype=object)
的对象,我不确定如何使用它?你的第二个解决方案适用于我的简单示例,但我认为它不能很好地推广,例如,当生成的数组更大时(需要更多的赋值形式
res[:,I]=…
)。在Py3中,你必须使用
列表(map(…)
)。或者尝试
np.array([fn(i)代表arr中的i])
@Marein:正如hpaulj所说,您必须在Python 3中使用
list(map())
。我更新了我的答案。我还更新了我的第二个解决方案,使其完全通用,但速度仍然很快。您的第一个解决方案生成了一个形式为
数组(,dtype=object)
的对象,我不知道如何使用它?你的第二个解决方案适用于我的简单示例,但我认为它不能很好地推广,例如,当生成的数组更大时(需要更多的赋值形式
res[:,I]=…
)。在Py3中,你必须使用
列表(map(…)
)。或者尝试
np.array([fn(i)代表arr中的i])
@Marein:正如hpaulj所说,您必须在Python 3中使用
list(map())
。我更新了我的答案。我还更新了我的第二个解决方案,使之完全通用,但仍然很快。我也想到了类似的解决方案,但不知道如何编写它。一个不错的解决办法。然而,什么样的重塑会产生我所需要的
res
呢?我找到了两种方法来重塑结果,使其符合我的要求,例如:
res.reformate(4,2,order='F')
res.reformate(4,2).T
。尽管在我的实际用例中,似乎只是在不指定
顺序
或转置结果的情况下进行重塑就足够了。我还不太理解其中的机制……我也有类似的想法作为解决方案,但不知道如何编写它。一个不错的解决办法。然而,什么样的重塑会产生我所需要的
res
呢?我找到了两种方法来重塑结果,使其符合我的要求,例如:
res.reformate(4,2,order='F')
res.reformate(4,2).T
。尽管在我的实际用例中,似乎只是在不指定
顺序
或转置结果的情况下进行重塑就足够了。我还不太懂机械原理。。。