2015-04-11 3 views
1

Предположим, у меня есть a где a.shape является (m*n,), как создать новый массив, который включает в себя следующие m суммы каждой группы n элементов эффективно?Как суммировать массив numpy размера (m * n,) в группах по m?

Лучшее, что я придумал это:

a.reshape((m, n)).sum(axis=1) 

, но это создает дополнительный новый массив.

+1

Что вы подразумеваете под '(mn,)'? Это кортеж длиной один, содержащий только переменную, называемую 'mn'? Если нет, что вы имеете в виду? Если да, то что такое 'm' и' n'? – KSFT

+0

@KSFT: просто умножение; Я сделаю это более ясным. –

ответ

3

Существует еще один трюк, вариант на cumsum, reduceat. В этом случае

np.add.reduceat(a, np.arange(0,m*n,n)) 

Для m,n=100,10, это 2x так быстро, как x.reshape((m,n)).sum(axis=1).

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

+1

+1 Вау, я никогда не слышал о 'reduceat'! Это может быть полезно заменить некоторые уродливые хаки, которые я делал с cumsum в прошлом. –

6

Я думаю, что нет ничего плохого в использовании reshape, а затем взяв сумму строк, я больше ничего не могу придумать. Согласно manual, reshape должен (если возможно) возвращать представление на исходном массиве, поэтому не копируется большой объем данных. Когда создается представление, numpy только создает новый заголовок с разными шагами и формой с указателем на данные исходного массива. Это должно стоить постоянное время и память, независимо от размера массива.

In [23]: x = np.arange(12) 

In [24]: y = x.reshape((3, 4)) 

In [25]: y 
Out[25]: 
array([[ 0, 1, 2, 3], 
     [ 4, 5, 6, 7], 
     [ 8, 9, 10, 11]]) 

In [26]: y.base is x # check if it is a view 
Out[26]: True 
+0

Ах! Не знал, что это дает представление! –

+0

Лучше всего суммировать итоговую ось, не так ли? –

+0

Возможно, это верно для стандартных массивов, поскольку для больших массивов вы будете получать доступ к соседним элементам в памяти, что лучше для кеширования. Но попробуйте сами в ipython, создав 'x = np.arange (1000000) .reshape (1000,1000)' и выполнив 'timeit x.sum (axis = 0)' и аналогичный для 'axis = 1'. На моей машине вторая на 25% быстрее. Это, вероятно, будет зависеть от конкретных размеров машины, массива, и если ваш массив использует макет памяти в стиле C или Fortran. –

Смежные вопросы