Numpy collapse columns according to list
<p>In numpy, I have a d x n array A and a list L of length n describing where I want each column of A to end up in matrix B. The idea is that column i of matrix B is the sum of all columns of A for which the corresponding value in L is i. I can do this with a loop:</p>

<pre><code>A = np.arange(15).reshape(3,5)
L = [0,1,2,1,1]
n_cols = 3
B = np.zeros((len(A), n_cols)) 
# assume I know the desired number of columns, 
# which is also one more than the maximum value of L
for i, a in enumerate(A.T):
    B[:, L[i]] += a
</code></pre>

<p>Is there a way to do this by slicing array A (or in some otherwise vectorized manner)?</p>

<p>Is this iteration on ``B` the same (not tested)?</p>

<pre><code> for I in range(B.shape[1]):
       B[:, I] = A[:, L==I].sum(axis=1)
</code></pre>

<p>The number loops will be fewer.  But more importantly it may give other vectorization insights.</p>

<p>(edit) on testing, this works, but is much slower.</p>

<p>+========</p>

<p><code>scipy.sparse</code> does column sum with matrix product with a matrix of ones.  Can we do the same here?  Make <code>C</code> array with 1s in the right columns</p>

<pre><code>def my2(A,L):
    n_cols = L.shape[0]
    C = np.zeros((n_cols,n_cols),int)
    C[np.arange(n_cols), L] = 1
    return A.dot(C)
</code></pre>

<p>This is 7x faster than your loop, and slightly faster than <code>@Divakars</code> <code>reduceat</code> code.</p>

<p>==========</p>

<pre><code>In [126]: timeit vectorized_app(A,L)
The slowest run took 8.16 times longer than the fastest. This could mean that an intermediate result is being cached.
10000 loops, best of 3: 99.7 Âµs per loop
In [127]: timeit val2 = my2(A,L)
The slowest run took 10.46 times longer than the fastest. This could mean that an intermediate result is being cached.
10000 loops, best of 3: 81.6 Âµs per loop
In [128]: timeit org1(A,n_cols)
1000 loops, best of 3: 623 Âµs per loop
In [129]: d,n_cols
Out[129]: (10, 100)
</code></pre>

python numpy vectorization numpy-broadcasting