<p>像这样的矢量化的一般方法是使用广播来创建集合本身的笛卡尔积。在您的例子中,您有一个形状为<code>arr</code>的数组,因此您可以对其进行两个视图:</p>
<pre><code>arr_x = arr[:, :, np.newaxis, np.newaxis, :] # shape (200, 600, 1, 1, 20)
arr_y = arr[np.newaxis, np.newaxis, :, :, :] # shape (1, 1, 200, 600, 20)
</code></pre>
<p>为了清楚起见,以上两行已经展开,但我通常会写出等价的:</p>
<pre><code>arr_x = arr[:, :, None, None]
arr_y = arr
</code></pre>
<p>如果您有一个向量化函数<code>f</code>,它在除了最后一个维度之外的所有维度上广播,那么您可以:</p>
<pre><code>out = f(arr[:, :, None, None], arr)
</code></pre>
<p>然后<code>out</code>将是一个形状为<code>(200, 600, 200, 600)</code>的数组,其中<code>out[i, j, k, l]</code>保持<code>f(arr[i, j], arr[k, l])</code>的值。例如,如果要计算所有成对内部产品,可以执行以下操作:</p>
<pre><code>from numpy.core.umath_tests import inner1d
out = inner1d(arr[:, :, None, None], arr)
</code></pre>
<p>不幸的是<code>scipy.stats.kendalltau</code>不是这样矢量化的。根据<a href="http://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.kendalltau.html" rel="noreferrer">the docs</a></p>
<blockquote>
<p>"If arrays are not 1-D, they will be flattened to 1-D."</p>
</blockquote>
<p>所以你不能这样做,你最终会做Python嵌套循环,不管是显式地写出来,使用<code>itertools</code>还是隐藏在<a href="http://docs.scipy.org/doc/numpy/reference/generated/numpy.vectorize.html" rel="noreferrer">^{<cd10>}</a>下。这将是缓慢的,因为Python变量上的迭代,并且因为每个迭代步骤都有一个Python函数,这两个操作都很昂贵。</p>
<p>请注意,当您可以采用矢量化的方式时,有一个明显的缺点:如果您的函数是可交换的,即如果<code>f(a, b) == f(b, a)</code>,那么您所做的计算是所需的两倍。根据实际计算的开销,这通常会被没有任何Python循环或函数调用所带来的速度提高所抵消。</p>