Numpy - Как векторизовать подмассивы - PullRequest
0 голосов
/ 18 июня 2020

Как вы применяете векторизованные функции к подмассивам? Предположим, у меня есть следующее:

array = np.array([
    [0, 1, 2],
    [2],
    [],
])

И я хотел получить первый элемент в каждом подмассиве, иначе None.

[0, 2, None]

Хотя это просто, Есть ли способ сделать это, используя чистую векторизацию Numpy? Кажется, что нет собственных операций, а функция np.vectorize() описана как неверная документация и была указана в различных других точках в потоках.

Это мой единственный вариант np.apply_along_axes() ?

Когда я узнаю, что не могу решить свою проблему с помощью чистой векторизации numpy?

1 Ответ

1 голос
/ 18 июня 2020

Вы создали массив объекта dtype, содержащий списки (не подмассивы):

In [2]: array = np.array([ 
   ...:     [0, 1, 2], 
   ...:     [2], 
   ...:     [], 
   ...: ])                                                                      
/usr/local/bin/ipython3:4: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (1.19dev gives warning)
In [3]: array                                                                   
Out[3]: array([list([0, 1, 2]), list([2]), list([])], dtype=object)

Мы могли бы использовать понимание списка:

In [4]: [a[0] for a in array]                                                   
....
IndexError: list index out of range

и исправление пустого списка :

In [5]: [a[0] if a else None for a in array]                                    
Out[5]: [0, 2, None]

Большая часть быстро скомпилированного кода для numpy - «векторизованного» материала - работает только с массивами numeri c dtype. Для объекта dtype он должен делать что-то вроде понимания списка. Даже когда математика работает, это потому, что она могла делегировать действие элементам.

Например, применение репликации списка ко всем элементам вашего массива:

In [7]: array*3                                                                 
Out[7]: 
array([list([0, 1, 2, 0, 1, 2, 0, 1, 2]), list([2, 2, 2]), list([])],
      dtype=object)

и sum - это просто соединение списка:

In [8]: array.sum()                                                             
Out[8]: [0, 1, 2, 2]

apply_along_axis isn ' t быстрее, чем np.vectorize. И я не могу представить, как это можно было бы использовать в таком случае. array равно 1d.

Иногда frompyfunc удобно при работе с массивами объектов dtype (но это не решение для скорости):

In [11]: timeit np.frompyfunc(lambda a: a[0] if a else None, 1,1)(array)        
3.8 µs ± 9.85 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [12]: timeit [a[0] if a else None for a in array]                            
1.02 µs ± 5.6 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
In [14]: timeit np.vectorize(lambda a: a[0] if a else None, otypes=['O'])(array)                                                                    
18 µs ± 46.2 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...