在numpy.apply_along_axis(func1d,axis,arr,* args,** kwargs)中传递一个列表作为func1d的参数

时间:2018-06-20 15:16:45

标签: python-3.x numpy

我无法将列表作为参数传递给numply.apply_along_axis(...)中的func1d。

def test(a, value):
    print(value)
    return a

a = np.zeros((49), dtype=list) 
kwargs = {"value":[1,1,1]}
zep = np.vectorize(test)
np.apply_along_axis(zep, 0, a, **kwargs)

出局:

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/ibpc/osx/lbt/numpy/1.9.2/lib/python3.4/site-packages/nump/lib/shape_base.py", line 91, in apply_along_axis
res = func1d(arr[tuple(i.tolist())], *args, **kwargs)
File "/ibpc/osx/lbt/numpy/1.9.2/lib/python3.4/site-packages/numpy/lib/function_base.py", line 1700, in __call__
return self._vectorize_call(func=func, args=vargs)
File "/ibpc/osx/lbt/numpy/1.9.2/lib/python3.4/site-packages/numpy/lib/function_base.py", line 1769, in _vectorize_call
outputs = ufunc(*inputs)
ValueError: operands could not be broadcast together with shapes (49,) (3,) 

所以,他希望我的len(kwargs [“ value”])== 49。但这不是我想要的。 如果需要,我需要更改值(在numpy.apply_along_axis(func1d)中,我需要更新列表)。

如何将列表作为参数传递?或者可以使用另一种方法来解决此问题。

实际上,我在粒子的3D空间中具有一个numpy.array的位置列表。 像这样:

dim = [49,49,49]
dx = 3
origin = [3,3,3]
nb_iter = 5
ntoto=np.load("ntoto.npy")
ntoto = ntoto.flatten()
liste_particles=np.zeros((5), dtype=list)
for i in range(len(liste_particles)):
    liste_particles[i]=[[r.uniform(0,150),r.uniform(0,150),r.uniform(0,150)]]*nb_iter #nb_iter is just the number of iteration I want to do in calcTrajs. 
vtraj=np.vectorize(calcTrajs, otypes=[list])
np.apply_along_axis(vtraj, 0, liste_particules)

在这里,我有五个随机放置的粒子。此外,我还有另一个numpy.array(shape ==(49,49,49)),其中包含一个vector_field。

这是我需要运行的func1d:

def calcTrajs(a): 
    global ntoto, dim, dx, origin #ntoto is my vector_field
    for b in range(1,len(a)):
        ijk = s2g(a[b-1], dx, origin, dim) # function to have on which vector my particle is.(space to grid, because my vector_field is like a grid). 
        value = np.asarray(ntoto[flatten3Dto1D(ijk, dim[1], dim[2])]) # so value contains the vector who influence my particle. 
        try:
            a[b] = list(a[b-1] + value*1000)
        except:
            print("error")
            break 
     return a

此函数允许我在vector_field中发射粒子并计算其轨迹。 如您所见,我放入了全局变量。但我想将此变量作为参数而不是全局变量传递。 ntoto是一个numpy.array,dim是一个列表(我的向量字段的维数),dx是单元格的间隔(因为我的vector_field在包含许多单元格的网格中,每个单元格都包含一个向量),并且起点是我的网格。

最诚挚的问候,

亚当

1 个答案:

答案 0 :(得分:0)

正如我所评论的,vectorizeapply...都不是速度工具。 vectorize对于相互广播多个阵列很有用。 apply ...对于迭代2个以上的维度非常有用。只用一两个,就太过分了。两者都是初学者经常滥用的工具。

尽管我尚未测试apply_along_axis部分,但看起来还可以。错误在于vectorize中的广播。

尤其是因为您将a定义为对象dtype,因此应为vectorize指定类似return dtype的内容。否则,它将执行测试计算以确定它。

In [223]: def test(a, value):
     ...:     print(value)
     ...:     return a
In [224]: zep = np.vectorize(test, otypes=['O'])
In [225]: a = np.array([[1,2,3],[4,5]])
In [226]: a
Out[226]: array([list([1, 2, 3]), list([4, 5])], dtype=object)

zepa和标量一起使用

In [227]: zep(a,1)
1
1
Out[227]: array([list([1, 2, 3]), list([4, 5])], dtype=object)

但是,当a有2个项目,而value有3个项目时,我会得到与您相同的错误:

In [228]: zep(a,[1,2,3])
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-228-382aaa7a2dc6> in <module>()
----> 1 zep(a,[1,2,3])

/usr/local/lib/python3.6/dist-packages/numpy/lib/function_base.py in __call__(self, *args, **kwargs)
   2753             vargs.extend([kwargs[_n] for _n in names])
   2754 
-> 2755         return self._vectorize_call(func=func, args=vargs)
   2756 
   2757     def _get_ufunc_and_otypes(self, func, args):

/usr/local/lib/python3.6/dist-packages/numpy/lib/function_base.py in _vectorize_call(self, func, args)
   2829                       for a in args]
   2830 
-> 2831             outputs = ufunc(*inputs)
   2832 
   2833             if ufunc.nout == 1:

ValueError: operands could not be broadcast together with shapes (2,) (3,) 

(2,)和(2,)很好:

In [229]: zep(a,['a','b'])
a
b
Out[229]: array([list([1, 2, 3]), list([4, 5])], dtype=object)

(2,)与(2,1)也是,产生(2,2)输出。这是vectoring可以提供帮助的一种广播示例。

In [230]: zep(a,[['a'],['b']])
a
a
b
b
Out[230]: 
array([[list([1, 2, 3]), list([4, 5])],
       [list([1, 2, 3]), list([4, 5])]], dtype=object)