2017-10-03 1 views
0

wie Cumsum n aufeinander folgende Elemente in jeder Spalte durch eine Liste angegeben. Cumsum wird ab der nächsten Reihe zurückgesetzt. Zum Beispiel Objektiv = [2,3] ==> cumsum der ersten 2 Reihen [: 2], und dann für die nächsten cumSum 3 Reihen [2: 5]Numpy Cumsum Spalten für unterschiedliche Längen durch Liste angegeben

import numpy as np 
lens = [3, 2] 
a = np.array(
     [[ 1, 2], 
     [ 1, 2], 
     [ 1, 2], 
     [ 1, 2], 
     [ 1, 2]]) 

geben

np.array(
     [[ 1, 2], 
     [ 2, 4], 
     [ 3, 6], 
     [ 1, 2], 
     [ 2, 4]]) 

versucht Schleifen

+1

Sollte die letzte Reihe im Ergebnis be '[2, 4] '? – BradMcDanel

Antwort

3

Eine Möglichkeit zu vermeiden, ist das Array, cumsum aufgeteilt und dann kombinieren:

np.concatenate(list(map(lambda a: np.cumsum(a, axis=0), np.array_split(a, np.cumsum(lens))))) 
#array([[1, 2], 
#  [2, 4], 
#  [3, 6], 
#  [1, 2], 
#  [2, 4]], dtype=int32) 

Eine weitere Möglichkeit, ohne Split und kombinieren ist ein Hilfsarray zu schaffen, der die Summe an bestimmten Index wie unten zurückgesetzt:

idx = np.cumsum([0] + lens)[:-1] 
aux = np.zeros_like(a) 
aux[idx[1:], :] = -np.add.reduceat(a, idx)[:-1] 
(a + aux).cumsum(0) 

#array([[1, 2], 
#  [2, 4], 
#  [3, 6], 
#  [1, 2], 
#  [2, 4]], dtype=int32) 

Die beiden Methoden sind etwa der gleichen Geschwindigkeit:

def split_concat(a): 
    return np.concatenate(list(map(lambda a: np.cumsum(a, axis=0), np.array_split(a, np.cumsum(lens))))) 

def reset_sum(a): 
    idx = np.cumsum([0] + lens)[:-1] 
    aux = np.zeros_like(a) 
    aux[idx[1:], :] = -np.add.reduceat(a, idx)[:-1] 
    return (a + aux).cumsum(0) 


lens = np.arange(1000) 
a = np.ones((lens.sum(), 2)) 
(reset_sum(a) == split_concat(a)).all() 
# True 

%timeit split_concat(a) 
# 12.8 ms ± 35.1 µs per loop (mean ± std. dev. of 7 runs, 100 loops each) 

%timeit reset_sum(a) 
# 13.6 ms ± 87.4 µs per loop (mean ± std. dev. of 7 runs, 100 loops each) 
Verwandte Themen