split
создает список массивов, которые могут отличаться по длине.Это фактически делает итеративно
In [12]: alist = []
In [13]: alist.append(a[0:idx[0]])
In [14]: alist.append(a[idx[0]:idx[1]])
In [15]: alist.append(a[idx[1]:idx[2]])
....
Применение sum
к каждому элементу списка в отдельности имеет смысл:
In [11]: [np.sum(row) for row in alist]
Out[11]: [6, 39, 60, 85]
Когда у вас есть список массивов, которые отличаются по форме, этохорошая ставка, что вам придется делать итерацию уровня Python на нем.
Быстрая «векторизация» означает выполнение вычислений в скомпилированном коде.Большинство из них построены вокруг многомерных массивов, например, 2d.Если ваш split
создал массив одинакового размера, вы можете использовать np.sum
с соответствующим параметром оси.
In [23]: a1 = a.reshape(4,5)
In [24]: a1
Out[24]:
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19]])
In [25]: np.sum(a1, axis=1)
Out[25]: array([10, 35, 60, 85])
Иногда мы можем разыграть трюки, чтобы привести проблему к nd, например, если вашпервый массив разбиения был дополнен 0. Но само приведение может потребовать итерации.
Как поднято здесь (и его ссылки) Происхождение AttributeError: у объекта нет атрибута 'cos' математические (ufunc
) функции, применяемые к массивам объектов dtype, заканчивают делегированием действия соответствующим методам объектов.Но это все еще включает (почти) итерацию уровня Python над объектами.
Некоторые моменты времени:
In [57]: timeit [np.sum(row) for row in alist]
31.7 µs ± 1.21 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [58]: timeit np.sum(list(itertools.zip_longest(*alist, fillvalue=0)),axis=0)
25.2 µs ± 82 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [59]: timeit np.nansum(pd.DataFrame(alist), axis=1)
908 µs ± 28.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [61]: timeit np.frompyfunc(sum,1,1)(alist)
12.9 µs ± 21.9 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
В этом последнем случае Python sum
быстрее, чем np.sum
.Но это верно и для понимания списка:
In [63]: timeit [sum(row) for row in alist]
6.86 µs ± 13.7 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
И с помощью wiz-bang Дивакара fillna
, Numpy: исправить массив со строками разной длины, заполнив пустые элементы нулями
In [70]: timeit numpy_fillna(np.array(alist)).sum(axis=1)
44.2 µs ± 208 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
Если у вас есть многомерный массив, код Numpy работает быстро.Но если начать со списка, даже со списком массивов, методы списка Python часто работают быстрее.Время, необходимое для создания массива (или Dataframe), никогда не бывает тривиальным.