2017-10-02 1 views
0

Ich bin ein großer Satz von Positionen zu unterschiedlichen Zeitpunkten, als eine spärliche Matrix Verwaltung: eine Anordnung von Positionen (die Spalten) und eine Reihe von Zeiten mit der gleichen Größe. Z.B.numpy/tensorflow Vektorisierung von Scheiben

matrix = numpy.random.randint(2, size = 100).astype(float).reshape(10,10) 
times = numpy.nonzero(matrix)[0]+1 
positions = numpy.nonzero(matrix)[1] 

Jetzt muss ich die Positionen mit den Geschwindigkeiten zu einer Zeit zugeordnet korrigieren. Das Problem besteht darin, dass ich als spärliche Matrix die mit einer Zeit verbundene Geschwindigkeit auf jede Position zu einer bestimmten Zeit (d. H. Auf jedes Element ungleich Null in einer gegebenen Reihe) erweitern muss. Ich kenne die Indizes der ersten Position zur angegebenen Zeit und die Anzahl der Male nTimes Wie kann ich diesen Code vektorisieren (d. H. Die Schleife entfernen)?

indexes = numpy.where(numpy.diff(times)>0)[0]+1 
indexes = numpy.concatenate(([0],indexes, [times.size])) 
nTimes = numpy.size(indexes)-1 
speeds = numpy.random.rand(nTimes) 

starts = indexes[:-1] 
ends = indexes[1:] 
expandedSpeeds = numpy.zeros(positions.size) 
for i in numpy.arange(0,nTimes): 
    expandedSpeeds[starts[i]:ends[i]] = speeds[i] 

Bearbeitet, um ein ausführbares Beispiel zu geben.

+0

In Ihrem Beispiel finde ich mehrere Dinge verwirrend. Was sind Indizes? Wenn 'expandedSpeeds' eine erste Dimension der Größe 3 hat, ist diese Indizierung in der letzten Zeile etwas merkwürdig. Auf der rechten Seite der letzten Zeile haben Sie grundsätzlich 'Geschwindigkeiten [i]' (außer es in einem Array ist). Könnten Sie bitte einen runnable MCVE in Ihre Frage einfügen? –

+1

Ja, Sie haben recht, es tut mir so leid, ich habe ein Durcheinander gemacht, indem ich den Code kopiert und versucht habe, das Problem zu vereinfachen. Das 'indexes'-Array ist' numpy.where (numpy.diff (mal)> 0) '. Ich werde ein lauffähiges Beispiel schreiben. – LolAsdOmgWtfAfk

+1

@AndrasDeak jetzt können Sie den Code versuchen, sollte es richtig funktioniert, danke und Entschuldigung wieder. – LolAsdOmgWtfAfk

Antwort

1

Ich versuchte funktionalisieren dem ursprünglichen Ansatz und hier ist, was ich habe -

def slices2arr_vect(ar, starts, ends, N): 
    id_arr = np.zeros((N),dtype=int) 
    id_arr[starts[1:]] = 1 
    c = id_arr.cumsum() 

    np.add.at(id_arr, ends[1:],-1) 
    out = np.where(id_arr.cumsum()==0, 0, ar[c]) 
    out[starts[0]:ends[0]] = ar[0] 
    return out 
-

def slices2arr_org(ar, starts, ends, N): 
    out0 = np.zeros((N),dtype=ar.dtype) 
    for i in np.arange(n_grp): 
     out0[starts[i]:ends[i]] = ar[i:i+1] 
    return out0 

Jetzt ist es vektorisieren, wir Verwendung der kumulativen Summierung und einige Maskierung, wie so machen könnte

Hier ist ein Beispiel ausgeführt, um die Dinge klarer zu machen -

In [677]: # Setup inputs 
    ...: np.random.seed(0)  
    ...: n_grp = 5 
    ...: N = 15 
    ...: idx = np.sort(np.random.choice(N, n_grp*2, replace=0)) 
    ...: starts, ends = idx[::2], idx[1::2]      
    ...: ar = np.random.randint(11,99,(N)) 
    ...: 

In [678]: ar 
Out[678]: array([76, 50, 98, 57, 92, 48, 36, 88, 83, 20, 31, 91, 80, 90, 58]) 

In [679]: starts 
Out[679]: array([ 1, 4, 7, 9, 13]) 

In [680]: ends 
Out[680]: array([ 2, 6, 8, 10, 14]) 

In [681]: slices2arr_org(ar, starts, ends, N) 
Out[681]: array([ 0, 76, 0, 0, 50, 50, 0, 98, 0, 57, 0, 0, 0, 92, 0]) 

In [682]: slices2arr_vect(ar, starts, ends, N) 
Out[682]: array([ 0, 76, 0, 0, 50, 50, 0, 98, 0, 57, 0, 0, 0, 92, 0]) 
+0

Vielen Dank, ich könnte nie Cumsum verwenden, um das Problem zu lösen. Wenn Sie einen kleinen Hinweis wünschen, ist np.ufunc.at leider sogar langsamer als eine Pythonschleife (!). Ihre Funktion funktioniert gut, auch mit einer einfachen Sammlung mit np.take oder _fancy_ Indizierung (wie numpy docs nennt es xD): 'id_arr [Enden [1:]] = id_arr [Enden [1:]] - 1 '. Auf diese Weise läuft Che Code zweimal schneller;) – LolAsdOmgWtfAfk