2013-05-14 3 views
19

Может ли кто-нибудь рекомендовать способ сделать обратную суммарную сумму на массив numpy?Выполнить обратную суммарную сумму на массив numpy

Где обратная накопленная сумма "определяется, как показано ниже (я приветствую какие-то корректировки на имя для этой процедуры):

если таковые

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

затем

np.cumsum(x) 

дает

array([0,1,3,6,10]) 

Тем не менее, я хотел бы получить

array([10,10,9,7,4] 

Может кто-нибудь предложить способ сделать это?

ответ

34

Это делает:

np.cumsum(x[::-1])[::-1] 
+0

Эквивалентный способ, но различный синтаксис: х [:: - 1] .cumsum() [:: - 1] – Staza

-2

Для удовольствия, используя анонимные функции:

array = [0,1,2,3,4] 

reverse = lambda a: a[::-1] 
cumsum = lambda a: [ sum(a[:i+1]) for i,x in enumerate(a) ] # there is also an accumulate function present in the itertools module 

print reverse(array) 
print cumsum(array) 

# sadly, no compose function in Python 
reverse_cumsum = lambda a: reverse( cumsum (reverse(a))) 

print reverse_cumsum(array) 

Результат:

[4, 3, 2, 1, 0] 
[0, 1, 3, 6, 10] 
[10, 10, 9, 7, 4] 
+2

FYI: 'a = np.random.randint (100, size = (1000))', '% timeit reverse_cumsum (a)': '1 петли, лучше всего 3: 315 мс за цикл','% timeit np.cumsum (a [:: - 1]) [:: - 1] ':' 100000 циклов, лучше всего 3: 8,89 мкс за цикл'. (Если я переключусь с вашего 'cumsum' на numpy's, тогда будет' 9,75 мкс за цикл', поэтому вызовы функций не добавляют слишком много накладных расходов, это всего лишь реализация in-python-and-repeat-summing-for- не-реальная причина, которая замедляет 35000 раз.) – Dougal

9

Только для записи: np.sum(x) - np.cumsum(x) также , но на больших массивах (где скорость имеет значение) она вдвое быстрее:

In [8]: x = np.ones(1e8) 

In [9]: %timeit np.cumsum(x[::-1])[::-1] 
1 loops, best of 3: 547 ms per loop 

In [10]: %timeit np.sum(x) - np.cumsum(x) 
1 loops, best of 3: 974 ms per loop 

и менее элегантно, когда хочет сделать cumsum вдоль некоторой размерности, кроме первого:

x = np.ones((1e3,1e3)) 
np.sum(x,axis=-1)[:,np.newaxis] - np.cumsum(x,axis=-1) 
1

Вы можете использовать .flipud() для этого, а также, что эквивалентно [::-1] https://docs.scipy.org/doc/numpy/reference/generated/numpy.flipud.html

In [0]: x = np.array([0,1,2,3,4]) 

In [1]: np.flipud(np.flipud(x).cumsum()) 
Out[1]: array([10, 10, 9, 7, 4] 

.flip() является новинкой от NumPy 1.12 и объединяет .flipud() и .fliplr() в один API. https://docs.scipy.org/doc/numpy/reference/generated/numpy.flip.html

Это эквивалентно, и имеет меньшее количество вызовов функции:

np.flip(np.flip(x, 0).cumsum(), 0) 
Смежные вопросы