scipy cdist或复数数组上的pdist

时间:2014-02-21 15:17:11

标签: python numpy scipy

使用scipy.spatial.distance.euclidean计算两个复数之间的欧几里德距离有效:

import numpy
import scipy.spatial.distance
z1 = numpy.complex(numpy.cos(0), numpy.sin(0))
z2 = numpy.complex(numpy.cos(3*numpy.pi/2), numpy.sin(3*numpy.pi/2))
print scipy.spatial.distance.euclidean(z1, z2)

给出:

1.4142135623730951

然而,成对距离矩阵或两个输入数组的每对之间的距离不起作用:

A = numpy.random.uniform(size=(5,1)) + numpy.random.uniform(size=(5,1))*1j
print scipy.spatial.distance.pdist(A)

返回警告以及实际部分之间的距离:

lib/python2.7/site-packages/scipy/spatial/distance.py:107: ComplexWarning: Casting complex values to real discards the imaginary part
X = X.astype(np.double)
array([ 0.78016544,  0.66201108,  0.8330932 ,  0.54355982,  0.11815436,
        0.05292776,  0.23660562,  0.17108212,  0.11845125,  0.28953338])

scipy.spatial.distance.cdist(A,A)相同。

是否可以使用cdist或pdist计算成对距离矩阵或每对输入数组之间的距离,而不使用for循环和scipy.spatial.distance.euclidean这对我的问题来说太慢了?

1 个答案:

答案 0 :(得分:2)

复数的欧几里德范数被定义为数的模数,然后你可以将两个复数之间的距离定义为它们之差的模数。

警告就在那里,因为pdistcdist是为N维(标量)空间设计的,其中这种距离概念没有任何意义。 (你如何处理许多维度,每个维度包含一个复数?对于标量很容易,但对于复杂的,你有几个选项)

给出两个积分:

A = numpy.random.uniform(size=(5)) + numpy.random.uniform(size=(5))*1j
B = numpy.random.uniform(size=(5)) + numpy.random.uniform(size=(5))*1j

A的每个点与B的每个点之间的距离可以计算为

MA = tile(A[:,newaxis],A.size)
MB = tile(B[:,newaxis],B.size)
dist = abs(MA-MB.T)

并且您将在dist[2][3]中获得集合A的第三个点与集合B的第四个点之间的距离。

这非常有效,如果像@ali_m在评论中建议的那样一步完成,

dist = np.abs(A[:, None] - B[None, :])

如果您只想要单个集合A的成对距离矩阵,则可以在上面的代码中将B替换为A。矩阵dist将是对称的,并且在对角线上将为零。因此,您将在循环中进行大约两倍的操作,并且占用的内存大约是所需内存的两倍。可能它仍然比带循环的解决方案更快(也因为循环你循环数字对)