How to use numpy.frompyfunc to return an array of elements instead of array of arrays?

雨燕双飞 提交于 2019-12-23 21:30:23

问题


I am using the PLegendre function from the SHTOOLS package. It returns an array of Legendre polynomials for a particular argument. PLegendre(lmax,x) returns an array of Legendre polynomials P_0(x) to P_lmax(x). It works like this:

In [1]: from pyshtools import PLegendre
loading shtools documentation

In [2]: import numpy as np

In [3]: PLegendre(3,0.5)
Out[3]: array([ 1.    ,  0.5   , -0.125 , -0.4375])

I would like to pass an array as a parameter, so I use frompyfunc.

In [4]: legendre=np.frompyfunc(PLegendre,2,1)

In [5]: legendre(3,np.linspace(0,1,4))
Out[5]: 
array([array([ 1. ,  0. , -0.5, -0. ]),
   array([ 1.        ,  0.33333333, -0.33333333, -0.40740741]),
   array([ 1.        ,  0.66666667,  0.16666667, -0.25925926]),
   array([ 1.,  1.,  1.,  1.])], dtype=object)

The output is an array of arrays. I understand that I can create an array of elements from this by slicing the array.

In [6]: a=legendre(3,np.linspace(0,1,4))

In [7]: array([a[i][:] for i in xrange(4)])
Out[7]: 
array([[ 1.        ,  0.        , -0.5       , -0.        ],
   [ 1.        ,  0.33333333, -0.33333333, -0.40740741],
   [ 1.        ,  0.66666667,  0.16666667, -0.25925926],
   [ 1.        ,  1.        ,  1.        ,  1.        ]])

But.. is there a way to get to this directly, instead of having to slice the array of arrays?


回答1:


I think it can not be done directly as already pointed out here in the case of np.vectorize which does almost the same thing. Note that your code is not faster then an ordinary for loop by using np.frompyfunc ... the code only looks nicer.

However, what you can do is using np.vstack instead of the list comprehension

a = legendre(3,np.linspace(0,1,4))
np.vstack(a)



回答2:


np.frompyfunc is compiled, so I'd have to dig into the source to see exactly what it is doing. But it appears to assume that the func output is an (inscrutable) Python object.

foo1 = np.frompyfunc(np.arange,1,1)
foo2 = np.vectorize(np.arange,otypes='O')

These 2 functions produce the same outputs, though foo1 is faster.

foo1(np.arange(4))

produces arrays with different sizes

array([array([], dtype=int32), array([0]), array([0, 1]), array([0, 1, 2])], dtype=object)

where as foo1(np.ones((4,)) are all the same, and in theory could be stacked.

There's no attempt, during the loop or after, to test whether the objects are arrays (or lists) and whether they can be combined into a single higher dimensional array.

plonser's use of vstack is a good idea. In fact frompyfunc plus vstack is faster than the more common list comprehension plus vstack.

In [54]: timeit np.vstack([np.arange(i) for i in 10*np.ones((10,))])
10000 loops, best of 3: 169 µs per loop

In [55]: timeit np.vstack(foo1(10*np.ones((10,))))
10000 loops, best of 3: 127 µs per loop


来源:https://stackoverflow.com/questions/29692875/how-to-use-numpy-frompyfunc-to-return-an-array-of-elements-instead-of-array-of-a

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!