Как использовать 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