2016-07-29 6 views
0

Ich habe Schwierigkeiten, die unter Betrieb in Vektorisierung:Numpy Probleme Vektorisierung bestimmte Art von Aggregation

# x.shape = (a,) 
# y.shape = (a, b) 
# x and y are ordered over a. 
# Want to combine x, y into z.shape(num_unique_x, b) 

# Below works and illustrates intent but is iterative 
z = np.zeros((num_unique_x, b)) 

for i in range(a): 
    z[x[i], y[i, :]] += 1 
+0

Irgendwelche Wiederholungen in 'x' oder' y'? Gib uns ein kleines diagnostisches Beispiel. – hpaulj

Antwort

1

Ihre Nutzung von num_unique_x, und die Größe der z legt nahe, dass dies ein Fall ist, wo x und y wiederholt haben, und dass einige der z größer als 1 sind. In diesem Fall müssen wir np.add.at verwenden. Aber um das einzurichten, würde ich seine Dokumentation überprüfen und möglicherweise einige Alternativen testen.

Aber zuerst ein nicht-wiederholt Fall

In [522]: x=np.arange(6) 
In [523]: y=np.arange(3)+x[:,None] 
In [524]: y 
Out[524]: 
array([[0, 1, 2], 
     [1, 2, 3], 
     [2, 3, 4], 
     [3, 4, 5], 
     [4, 5, 6], 
     [5, 6, 7]]) 

Sehen Sie, warum ich für ein diagnostisches Beispiel fragen. Ich denke über mögliche Werte. Ich muss eine z mit mehr als 3 Spalten machen.

In [529]: z=np.zeros((6,8),dtype=int) 
In [530]: for i in range(6): 
    ...:  z[x[i],y[i,:]]+=1 
In [531]: z 
Out[531]: 
array([[1, 1, 1, 0, 0, 0, 0, 0], 
     [0, 1, 1, 1, 0, 0, 0, 0], 
     [0, 0, 1, 1, 1, 0, 0, 0], 
     [0, 0, 0, 1, 1, 1, 0, 0], 
     [0, 0, 0, 0, 1, 1, 1, 0], 
     [0, 0, 0, 0, 0, 1, 1, 1]]) 

Das vektorisiert Äquivalent

In [532]: z[x[:,None],y] 
Out[532]: 
array([[1, 1, 1], 
     [1, 1, 1], 
     [1, 1, 1], 
     [1, 1, 1], 
     [1, 1, 1], 
     [1, 1, 1]]) 
In [533]: z[x[:,None],y] += 1 
In [534]: z 
Out[534]: 
array([[2, 2, 2, 0, 0, 0, 0, 0], 
     [0, 2, 2, 2, 0, 0, 0, 0], 
     [0, 0, 2, 2, 2, 0, 0, 0], 
     [0, 0, 0, 2, 2, 2, 0, 0], 
     [0, 0, 0, 0, 2, 2, 2, 0], 
     [0, 0, 0, 0, 0, 2, 2, 2]]) 

Der entsprechende add.at Ausdruck ist

In [538]: np.add.at(z,(x[:,None],y),1) 
In [539]: z 
Out[539]: 
array([[3, 3, 3, 0, 0, 0, 0, 0], 
     [0, 3, 3, 3, 0, 0, 0, 0], 
     [0, 0, 3, 3, 3, 0, 0, 0], 
     [0, 0, 0, 3, 3, 3, 0, 0], 
     [0, 0, 0, 0, 3, 3, 3, 0], 
     [0, 0, 0, 0, 0, 3, 3, 3]]) 

Also, die für diese nicht-wiederholt Fall funktioniert.

Für Wiederholungen in x:

In [542]: x1=np.array([0,1,1,2,3,5]) 
In [543]: z1=np.zeros((6,8),dtype=int) 
In [544]: np.add.at(z1,(x1[:,None],y),1) 
In [545]: z1 
Out[545]: 
array([[1, 1, 1, 0, 0, 0, 0, 0], 
     [0, 1, 2, 2, 1, 0, 0, 0], 
     [0, 0, 0, 1, 1, 1, 0, 0], 
     [0, 0, 0, 0, 1, 1, 1, 0], 
     [0, 0, 0, 0, 0, 0, 0, 0], 
     [0, 0, 0, 0, 0, 1, 1, 1]]) 

Ohne add.at verpassen wir die 2s.

In [546]: z2=np.zeros((6,8),dtype=int) 
In [547]: z2[x1[:,None],y] += 1 
In [548]: z2 
Out[548]: 
array([[1, 1, 1, 0, 0, 0, 0, 0], 
     [0, 1, 1, 1, 1, 0, 0, 0], 
     [0, 0, 0, 1, 1, 1, 0, 0], 
     [0, 0, 0, 0, 1, 1, 1, 0], 
     [0, 0, 0, 0, 0, 0, 0, 0], 
     [0, 0, 0, 0, 0, 1, 1, 1]]) 
+0

Fantastische Antwort, und ja Ihre Annahme von Wiederholungen innerhalb x ist richtig, und ich scheiterte an Ihrem letzten Beispiel, wo ich vermisst wurde, wie Sie sagten, die 2s. 'ufunc.at' ist eine nützliche Technik. –