Broadcast an operation along specific axis in python
<p>In python, suppose I have a square (numpy) matrix <strong>X</strong>, of size <em>n x n</em> and I have a numpy vector <strong>a</strong> of size <em>n</em>. </p>

<p>Very simply, I want to perform a broadcasting subtraction of <strong>X - a</strong>, but I want to be able to specify along which dimension, so that I can specify for the subtraction to be either along axis 0 or axis 1. </p>

<p>How can I specify the axis?</p>

<p>Thanks. </p>

<p>Start with 2 dimensions that are different (in label at least)</p>

<ul>
<li><code>X</code> shape <code>(n,m)</code></li>
<li><code>a</code> shape <code>(n,)</code></li>
<li><code>b</code> shape <code>(m,)</code></li>
</ul>

<p>The ways to combine these are:</p>

<pre><code>(n,m)-(n,) =&gt; (n,m)-(n,1) =&gt; (n,m)
X - a[:,None]     

(n,m)-(m,) =&gt; (n,m)-(1,m) =&gt; (n,m)
X - b[None,:]
X - b      # [None,:] is automatic, if needed.
</code></pre>

<p>The basic point is that when the number dimensions differ, <code>numpy</code> can add new dimensions at the start, but you have to be explicit about adding new dimensions at the end.</p>

<p>Or to combine 2 1d arrays in a outer product (difference):</p>

<pre><code>(n,) - (m,) =&gt; (n,1)-(1,m) =&gt; (n,m)
a[:,None] - b[None,:]
a[:,None] - b
</code></pre>

<p>Without the these rules, <code>a-b</code> could result in a <code>(n,m)</code> or <code>(m,n)</code> or something else.</p>

<p>And with 2 matching length arrays:</p>

<pre><code>(n,) - (n,) =&gt; (n,)
a - a
</code></pre>

<p>or </p>

<pre><code>(n,) - (n,) =&gt; (n,1)-(1,n) =&gt; (n,n)
a[:,None]-a[None,:]
</code></pre>

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

<p>To write a function that would take an <code>axis</code> parameter, you could use <code>np.expand_dims</code>:</p>

<pre><code>In [220]: np.expand_dims([1,2,3],0)
Out[220]: array([[1, 2, 3]])    # like [None,:]
In [221]: np.expand_dims([1,2,3],1)
Out[221]:             # like [:,None]
array([[1],
       [2],
       [3]])

def foo(X, a, axis=0):
    return X - np.expand_dims(a, axis=axis)
</code></pre>

<p>to be used as:</p>

<pre><code>In [223]: foo(np.eye(3),[1,2,3],axis=0)
Out[223]: 
array([[ 0., -2., -3.],
       [-1., -1., -3.],
       [-1., -2., -2.]])
In [224]: foo(np.eye(3),[1,2,3],axis=1)
Out[224]: 
array([[ 0., -1., -1.],
       [-2., -1., -2.],
       [-3., -3., -2.]])
</code></pre>

python arrays numpy matrix numpy-broadcasting