Вы создали массив объекта 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)