<p>使用嵌套的<code>for</code>循环进行此操作的替代方法要快得多。我将向您展示两种不同的方法-第一种方法将是更通用的方法,它将向您介绍广播和矢量化,第二种方法使用更方便的scipy库函数。</p>
<hr/>
<h2>一。一般方法,使用广播和矢量化</h2>
<p>我建议首先使用<code>np.array</code>,而不是<code>np.matrix</code>。数组是<a href="http://wiki.scipy.org/NumPy_for_Matlab_Users#head-e9a492daa18afcd86e84e07cd2824a9b1b651935" rel="noreferrer">a number of reasons</a>的首选,最重要的是因为它们可以具有>;2维,而且它们使按元素进行乘法变得不那么困难。</p>
<pre><code>import numpy as np
ncoord = np.array(ncoord)
</code></pre>
<p>使用数组,我们可以通过插入一个新的单例维度和<a href="http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html" rel="noreferrer">broadcasting</a>上的减法来消除嵌套的<code>for</code>循环:</p>
<pre><code># indexing with None (or np.newaxis) inserts a new dimension of size 1
print(ncoord[:, :, None].shape)
# (20, 2, 1)
# by making the 'inner' dimensions equal to 1, i.e. (20, 2, 1) - (1, 2, 20),
# the subtraction is 'broadcast' over every pair of rows in ncoord
xydiff = ncoord[:, :, None] - ncoord[:, :, None].T
print(xydiff.shape)
# (20, 2, 20)
</code></pre>
<p>这相当于使用嵌套for循环在每对行上循环,但要快得多!</p>
<pre><code>xydiff2 = np.zeros((20, 2, 20), dtype=xydiff.dtype)
for ii in range(20):
for jj in range(20):
for kk in range(2):
xydiff[ii, kk, jj] = ncoords[ii, kk] - ncoords[jj, kk]
# check that these give the same result
print(np.all(xydiff == xydiff2))
# True
</code></pre>
<p>剩下的我们也可以使用矢量化操作:</p>
<pre><code># we square the differences and sum over the 'middle' axis, equivalent to
# computing (x_i - x_j) ** 2 + (y_i - y_j) ** 2
ssdiff = (xydiff * xydiff).sum(1)
# finally we take the square root
D = np.sqrt(ssdiff)
</code></pre>
<p>整件事可以这样一字排开:</p>
<pre><code>D = np.sqrt(((ncoord[:, :, None] - ncoord[:, :, None].T) ** 2).sum(1))
</code></pre>
<hr/>
<h2>2。懒惰的方式,使用<code>pdist</code></h2>
<p>原来已经有了一个快速方便的函数来计算所有的成对距离:<a href="http://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.pdist.html" rel="noreferrer">^{<cd6>}</a>。</p>
<pre><code>from scipy.spatial.distance import pdist, squareform
d = pdist(ncoord)
# pdist just returns the upper triangle of the pairwise distance matrix. to get
# the whole (20, 20) array we can use squareform:
print(d.shape)
# (190,)
D2 = squareform(d)
print(D2.shape)
# (20, 20)
# check that the two methods are equivalent
print np.all(D == D2)
# True
</code></pre>