2016-09-18 6 views
1

Vor diesem Hintergrund (Beispiel) DatenVectorized sammeln Betrieb in numpy

target_slots = np.array([1, 3, 1, 0, 8, 5, 8, 1, 1, 2]) 
dummy_elements = np.arange(10*D).reshape(10, D) 

ist es eine Möglichkeit, die Operation in einem vektorisierten numpy Ausdruck auszudrücken

gathered_results = np.zeros((num_slots, D)) 
for i, target in enumerate(target_slots): 
    gathered_results[target] += dummy_elements[i] 

dieser Vorgang wie ein bincount aussieht, aber statt Zählen wir summieren die Elemente eines anderen Arrays.

(Es wird angedeutet, dass np.max(target_slots)<num_slots und np.min(target_slots)>=0 und target_slots.shape[0] == D)

+0

Warum ist 'D == len (target_slots) '? Geht dein Code nicht davon aus, dass 'len (target_slots) == 10'? – Eric

+1

@Eric Ich glaube nicht, 'D' soll' len (target_slots) 'sein. Ich denke, es ist nur ein Parameter. Können wir diesen Schnitt auf das ursprüngliche OP zurücksetzen? – Divakar

+0

Ich stimme @Divakar zu. 'target_slots' hat so viele Elemente wie die" Vektoren "in' dummy_elements' (jeweils Größe D). Man könnte sich diese Sammeloperation vorstellen, indem man die Vektoren in "dummy_elements" in die entsprechenden "target_slots" einfügt. Also 'len (target_slots) == dummy_elements.shape [0]' und 'D' ist ein Parameter – miltos

Antwort

1

Ansatz # 1

Sie führen intervall ed Summieren Reihen off dummy_elements und Hinzufügen in an bestimmten Zeilen in dem Ausgangsarray auswählt. Also, eine offensichtliche Wahl einer vektorisierten Lösung mit np.add.reduceat wäre, wie so -

sidx = target_slots.argsort() 
out = np.zeros((num_slots, D)) 
unq, shift_idx = np.unique(target_slots[sidx],return_index=True) 
out[unq] = np.add.reduceat(dummy_elements[sidx],shift_idx) 

Ansatz # 2

Alternativ können wir np.bincount verwenden auch diese ID basiert Summieren auszuführen Operationen. Ein Weg wäre mit einer Schleife, die entlang der Spalten von dummy_elements iteriert und ich denke, wäre von Vorteil, wenn die Nr. von solchen Säulen ist vergleichsweise kleiner. Die Umsetzung würde wie folgt aussehen -

out = np.zeros((num_slots, D)) 
L = target_slots.size 
for i in range(D): 
    out[:,i] = np.bincount(target_slots,dummy_elements[:,i],minlength=L) 

Ansatz # 3

Eine vektorisierte Version des gleichen so sein würde -

L = target_slots.size 
ids = (target_slots[:,None] + np.arange(D)*L).ravel('F') 
out = np.bincount(ids,dummy_elements.ravel('F'),minlength=L*D).reshape(D,-1).T 
+0

Danke. Aber wenn ich das richtig verstehe, setzt dies voraus, dass 'target_slots'" sortiert "/ interval-ed ist. Wenn also "target_slots = np.array ([8,8, 1, 3, 1, 8, 1, 9, 0, 1])" würde dies nicht wie erwartet funktionieren. Irgendwelche Vorschläge? – miltos

+0

(Ich habe die Frage bearbeitet, um die irreführende Konstruktion von 'target_slots' zu entfernen, die sortiert wurde, sorry für die Verwirrung) – miltos

+0

@miltos Nun, wir müssen nur die sortierten Indizes verwenden, um in Eingaben zu indizieren. Daher aktualisierte Lösung für die Behandlung von unsortierten Fällen. – Divakar