Как использовать numpy.frompyfunc для возврата массива элементов вместо массива массивов?

Я использую функцию PLegendre из пакета SHTOOLS. Он возвращает массив полиномов Лежандра для определенного аргумента. PLegendre(lmax,x) возвращает массив полиномов Лежандра от P_0(x) до P_lmax(x). Это работает так:

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])

Я хотел бы передать массив в качестве параметра, поэтому я использую 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)

Вывод представляет собой массив массивов. Я понимаю, что я могу создать массив элементов из этого, разрезая массив.

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.        ]])

Но... есть ли способ добраться до этого напрямую, вместо того, чтобы нарезать массив массивов?

2 ответа

Решение

Я думаю, что это не может быть сделано напрямую, как уже было указано здесь, в случае np.vectorize который делает почти то же самое. Обратите внимание, что ваш код не быстрее обычного for цикл с помощью np.frompyfunc... код выглядит только лучше.

Однако то, что вы можете сделать, это использовать np.vstack вместо понимания списка

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

np.frompyfunc компилируется, так что мне нужно копаться в источнике, чтобы точно узнать, что он делает. Но, похоже, предполагается, что вывод func является (непостижимым) объектом Python.

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

Эти 2 функции производят одинаковые выходы, хотя foo1 быстрее.

foo1(np.arange(4))

производит массивы с разными размерами

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

в то время как foo1(np.ones((4,)) все одинаковые, и в теории могут быть сложены.

Во время цикла или после него нет попытки проверить, являются ли объекты массивами (или списками) и могут ли они быть объединены в один массив более высокого измерения.

plonser's использование vstack хорошая идея по факту frompyfunc плюс vstack быстрее, чем более общее понимание списка плюс 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
Другие вопросы по тегам