Numpy: Matrix Array Shift / Einfügen nach Index

Ich habe ein Objekt, wo ich eine massive For-Loop-Methode in eine Reihe von vektorisierten numpy Arrays (ca. 50x schneller) umgewandelt haben. Jetzt versuche ich, eine neue Methode hinzuzufügen, wo ich mit einer numpy Matrix umgehen muss und dann "Subarray-Inhalte" (dh Einfügen von Werten) basierend auf dem Array-Index innerhalb der Matrix "verschieben" soll. Ich weiß, dass ich das mit einer for-Schleife erreichen kann, aber ich versuche es zu vermeiden, dass mit den beschleunigten Gewinnen durch die Verwendung von Vektor-Mathematik statt.

Ich frage mich, ob es einen schnellen und effizienten Weg gibt, um folgendes zu erreichen:

import numpy as np period = [1, 2, 3] x = [1, 10, 100] y = [.2, .4, .6] z = np.outer(x,y) print(z) 

Ergebnisse in:

 [[ 0.2 0.4 0.6] [ 2. 4. 6. ] [ 20. 40. 60. ]] 

Ich möchte die Zeilen in z verschieben, um die Anzahl der Nullen auf der Grundlage der Periode als Zeilenindex in z hinzuzufügen, im Grunde die folgenden:

 [[ 0.0 0.2 0.4 0.6 ] [ 0.0 0.0 2.0 4.0 6.0 ] [ 0.0 0.0 0.0 20.0 40.0 60.0 ]] 

Letztendlich würde ich auf die vertikale / säulenachse (achse = 1) summieren. Ich brauche ein endgültiges Array wie das folgende:

 [ 0.0 0.2 2.4 24.6 46.0 60.0] 

3 Solutions collect form web for “Numpy: Matrix Array Shift / Einfügen nach Index”

Sie können auch die Indizes zuerst berechnen und zuweisen:

 a = np.array( [[0.2 , 0.4 , 0.6], [2., 4., 6. ], [20., 40., 60. ]]) s0, s1 = a.shape rows = np.repeat(np.arange(s0), s1).reshape(a.shape) cols = (np.add.outer(np.arange(0, s0), np.arange(s1)) + 1) res = np.zeros((s0, s0 + s1)) res[rows, cols] = a np.sum(res,axis=0) >>> np.sum(res,axis=0) array([ 0. , 0.2, 2.4, 24.6, 46. , 60. ]) 
 [[ 0.0 0.2 0.4 0.6 ] [ 0.0 0.0 2.0 4.0 6.0 ] [ 0.0 0.0 0.0 20.0 40.0 60.0 ]] 

Ist eine zerlumpte Liste. Wir können das mit viectorized Array Magie bauen, zumindest nicht mit dem gewöhnlichen Zeug.

Um dies zu umgehen, müssen wir diese Struktur entweder flachlegen oder auflegen

 [[ 0.0 0.2 0.4 0.6 0.0 0.0] [ 0.0 0.0 2.0 4.0 6.0 0.0 ] [ 0.0 0.0 0.0 20.0 40.0 60.0 ]] 

oder

 [ 0.0 0.2 0.4 0.6 0.0 0.0 2.0 4.0 6.0 0.0 0.0 0.0 20.0 40.0 60.0 ] 

sum.reduceat lässt uns Blöcke eines flachen Arrays sum.reduceat , aber du willst eine Skip-Summe. Ich vermute, ich könnte die Abflachung der Transponierung erforschen.

Mein erster Gedanke war, dass das gepolsterte Array wie ein diagonalisiertes aussieht, das [.2,2,20] auf eine Diagonale, [.4,4,40] beim nächsten Offset, und so weiter. Ich weiß, sparse kann eine Matrix aus einer Matrix und Satz von Offsets zu bauen, aber ich glaube nicht, dass es eine solche Funktion in numpy . Sie alle arbeiten mit einem Offset zu einer Zeit.

Aber es sieht auch aus wie die Art von Offset, dass stride_tricks produzieren kann.

Lassen Sie uns das erforschen:

 In [458]: as_strided =np.lib.index_tricks.as_strided In [459]: Z=np.pad(z,[[0,0],[3,3]],mode='constant') In [460]: Z Out[460]: array([[ 0. , 0. , 0. , 0.2, 0.4, 0.6, 0. , 0. , 0. ], [ 0. , 0. , 0. , 2. , 4. , 6. , 0. , 0. , 0. ], [ 0. , 0. , 0. , 20. , 40. , 60. , 0. , 0. , 0. ]]) In [461]: Z.strides Out[461]: (72, 8) # prod an offset with (72+8, 8) In [462]: as_strided(Z,shape=(3,6),strides=(80,8)) Out[462]: array([[ 0. , 0. , 0. , 0.2, 0.4, 0.6], [ 0. , 0. , 2. , 4. , 6. , 0. ], [ 0. , 20. , 40. , 60. , 0. , 0. ]]) 

Das ist die Art von Schicht, die wir wollen, aber die Richtung ist falsch; So können wir Z :

 In [463]: Z1=Z[::-1,:].copy() In [464]: as_strided(Z1,shape=(3,6),strides=(80,8)) Out[464]: array([[ 0. , 0. , 0. , 20. , 40. , 60. ], [ 0. , 0. , 2. , 4. , 6. , 0. ], [ 0. , 0.2, 0.4, 0.6, 0. , 0. ]]) In [465]: as_strided(Z1,shape=(3,6),strides=(80,8)).sum(0) Out[465]: array([ 0. , 0.2, 2.4, 24.6, 46. , 60. ]) 

Verallgemeinerung kann dem Leser überlassen werden.

Ob Geschwindigkeitsvorteil ist unbekannt. Wahrscheinlich nicht für diesen kleinen Fall, vielleicht ja für einen sehr großen.


Das reinigt das Padding und schlägt ein bisschen

 In [497]: Z=np.pad(z,[[0,0],[1,4]],mode='constant') In [498]: Z.strides Out[498]: (64, 8) In [499]: as_strided(Z,shape=(3,6),strides=(64-8,8)) Out[499]: array([[ 0. , 0.2, 0.4, 0.6, 0. , 0. ], [ 0. , 0. , 2. , 4. , 6. , 0. ], [ 0. , 0. , 0. , 20. , 40. , 60. ]]) 

Dies ignoriert, wie z wurde. Wenn das äußere Produkt zentral für das Problem ist, könnte ich versuchen, das Schreiten auf dem 1d y , und verwenden Sie x , um eine gewichtete Summe durchzuführen.

 In [553]: x=np.array([1,10,100]); y=np.array([.2,.4,.6]) In [554]: z=np.concatenate(([0,0],y[::-1],[0,0,0])) In [555]: z Out[555]: array([ 0. , 0. , 0.6, 0.4, 0.2, 0. , 0. , 0. ]) In [556]: Z=as_strided(z,shape=(3,6), strides=(8,8)) In [557]: Z Out[557]: array([[ 0. , 0. , 0.6, 0.4, 0.2, 0. ], [ 0. , 0.6, 0.4, 0.2, 0. , 0. ], [ 0.6, 0.4, 0.2, 0. , 0. , 0. ]]) In [558]: np.dot(x,Z) Out[558]: array([ 60. , 46. , 24.6, 2.4, 0.2, 0. ]) 

In dieser Konstruktion ist Z eine Ansicht auf z , also kleiner als die Z in der vorherigen. Aber ich sage dot eine Kopie, wenn es es an den kompilierten Code sendet. np.einsum('i,ij',x,Z) könnte das vermeiden, indem es seine kompilierte Iteration der Ansicht macht, ohne es zu erweitern. Dies kann einen Unterschied machen, wenn es um sehr große Arrays geht.

Das Ergebnis ist umgekehrt, aber das ist leicht behoben. Ich kann es sogar während des Baus beheben.

Schleifen über die erste Dimension funktioniert:

 a = np.array( [[0.2 , 0.4 , 0.6], [2., 4., 6. ], [20., 40., 60. ]])​ s0, s1 = a.shape res = np.zeros((s0, s0 + s1)) for i in range(s1): res[i, i + 1: i + s0 + 1] = a[i] >>> np.sum(res,axis=0) array([ 0. , 0.2, 2.4, 24.6, 46. , 60. ])  a = np.array( [[0.2 , 0.4 , 0.6], [2., 4., 6. ], [20., 40., 60. ]])​ s0, s1 = a.shape res = np.zeros((s0, s0 + s1)) for i in range(s1): res[i, i + 1: i + s0 + 1] = a[i] >>> np.sum(res,axis=0) array([ 0. , 0.2, 2.4, 24.6, 46. , 60. ]) 
  • Schnelle (er) numpy fancy indexierung und reduktion?
  • Python Pandas: Maximale Anzahl von Zeilen erhöhen
  • Was ist das Äquivalent von "zip ()" in Python's numpy?
  • Implementierung von numpy in1d für 2D-Arrays?
  • Python: py2app "ImportError: dlopen (): Bibliothek nicht geladen"
  • Ich bekomme einen Fehler <string>: 149: RuntimeWarning: ungültiger Wert, der in sqrt bei der Erstellung einer Liste angetroffen wird
  • Wie installiere ich Python-Pakete ohne Root-Rechten?
  • Karte numpys `in1d` über 2D-Array
  • Verwenden von Numpy stride_tricks, um nicht überlappende Array-Blöcke zu erhalten
  • Numpy Laden csv TOO langsam im Vergleich zu Matlab
  • Setzen Sie das Element in das numpige Array ein
  • Python ist die beste Programmiersprache der Welt.