NumPy ndarray broadcasting - shape (X,) vs (X, 1)
<p>I have a NumPy <code>ndarray</code> which is shaped (32, 1024) and holds 32 signal measurements which I would like to combine into a single 1024 element long array, with a different weight for each of the 32. I was using <code>numpy.average</code> but my weights are complex and <code>average</code> performs a normalisation of the weights based on the sum which throws off my results.</p>

<p>Looking at the code for average I realised that I can accomplish the same thing by multiplying the weights by the signal array and then summing over the first axis. However when I try and multiply my (32,) weights array by the (32, 1024) signal array I get a dimension mismatch as the (32,) cannot be broadcast to (32, 1024). If I reshape the weights array to (32, 1) then everything works as expected, however this results in rather ugly code:</p>

<pre><code>avg = (weights.reshape((32, 1)) * data).sum(axis=0)
</code></pre>

<p>Can anybody explain why NumPy will not allow my (32,) array to broadcast to (32, 1024) and/or suggest an alternative, neater way of performing the weighted average?</p>

<p>On the question of why <code>(32,)</code> can't broadcast to <code>(32, 1024)</code>, it's because the shapes aren't aligned properly. To put it into a schematic, we have :</p>

<pre><code>weights :         32
data    :  32 x 1024 
</code></pre>

<p>We need to align the only axis, which is the first axis of <code>weights</code> aligned to the first axis of <code>data</code>. So, as you discovered one way is to <code>reshape</code> to <code>2D</code>, such that we would end up with a singleton dimension as the second axis. Going back to the schematic, with the modified version we would have :</p>

<pre><code>weights :  32 x    1
data    :  32 x 1024
</code></pre>

<p>Now, that the shapes are aligned, we can perform those elementwise operations.</p>

<p>We can explicitly introduce that new axis with <a href="http://docs.scipy.org/doc/numpy-1.10.0/reference/arrays.indexing.html#numpy.newaxis" rel="nofollow"><code>None/np.newaxis</code></a> and thus replace the <code>reshaping</code>, like so -</p>

<pre><code>(weights[:,None]*data).sum(0)
</code></pre>

<hr>

<p>Let's look for neat alternatives!</p>

<p>One neat and probably intuitive way would be with <a href="http://docs.scipy.org/doc/numpy/reference/generated/numpy.einsum.html" rel="nofollow"><code>np.einsum</code></a> -</p>

<pre><code>np.einsum('i,ij-&gt;j',weights,data)
</code></pre>

<p>Another way would be with matrix-multiplication using <a href="http://docs.scipy.org/doc/numpy/reference/generated/numpy.dot.html" rel="nofollow"><code>np.dot</code></a>, as we lose the first axis of <code>weights</code> against the first axis of <code>data</code>, like so -</p>

<pre><code>weights.dot(data)
</code></pre>

python numpy multidimensional-array numpy-broadcasting