我试图在两组粒子之间找到minimum image separation。我在每组中有大约40个粒子,它们的位置向量(三维)存储在两个维度(40, 3)
的数组中。在应用最小图像标准后,我必须计算一组中粒子的每个之间的欧几里德距离,以及另一组中粒子的每个之间的欧几里德距离。为了使其更清晰,对于两个列表pos1
和pos2
,其坐标为[func(i-j) for i in pos1 for j in pos2]
,其中func = lambda x: x - np.rint(x/width)*width
是一个适用的函数最低标准。
在三个维度中,欧几里德距离为numpy.sqrt(dx**2 + dy**2 + dx**2)
,其中dx
,dy
和dz
由func
为每个维度返回。
(函数func
只是为了演示如何应用最小图像标准。我不使用相同的精确程序结构。)
我正在寻找一种有效的方法,因为我必须在分析多个数据集时执行相同的操作,每个数据集的时间步长大约为 20000 ,每个步骤包含3个每组40个粒子,即每个时间步长计算的 6 组合组合。
谷歌搜索引导我scipy.spatial.distance.cdist
,但我在优化计算时间方面遇到了麻烦。内置的距离例程(Euclidean,Minkowski,Manhattan,Chebyshev等)经过优化并运行得非常快(在我下面的测试中高达三个数量级),与作为参数给出的显式函数定义相比较:
In [1]: import numpy as np
In [2]: from scipy.spatial.distance import cdist, euclidean
In [3]: %%timeit
...: pos1 = np.random.rand(40, 3)
...: pos2 = np.random.rand(40, 3)
...: cdist(pos1, pos2, metric='euclidean')
...:
The slowest run took 12.46 times longer than the fastest.
This could mean that an intermediate result is being cached
10000 loops, best of 3: 39.3 µs per loop
In [4]: %%timeit
...: pos1 = np.random.rand(40, 3)
...: pos2 = np.random.rand(40, 3)
...: cdist(pos1, pos2, metric=euclidean)
...:
10 loops, best of 3: 43 ms per loop
In [5]: %%timeit
...: pos1 = np.random.rand(40, 3)
...: pos2 = np.random.rand(40, 3)
...: cdist(pos1, pos2, lambda u, v: np.sqrt(((u-v)**2).sum()) )
...:
100 loops, best of 3: 15.5 ms per loop
In [6]: width = 1.0
In [7]: func = lambda x: x - np.rint(x/width)*width
In [8]: %%timeit
...: pos1 = np.random.rand(40, 3)
...: pos2 = np.random.rand(40, 3)
...: cdist(pos1, pos2, lambda u, v: np.sqrt(((func(u)-func(v))**2).sum()) )
...:
10 loops, best of 3: 31.2 ms per loop
以下是我考虑的选项:
x, y, x
组件,应用最小图像标准,并使用cdist
单独计算每个组件的欧氏距离(因为numpy.sqrt(dx**2) == dx
等等),reconstruct {{ 1}}来自组件数组的数组,并重复(40, 3)
以计算3D中的距离计算等效cdist
的有效方法是什么?
是否有任何内置的NumPy函数可以提供等效的cdist(pos1, pos2, lambda u, v: np.sqrt(((func(u)-func(v))**2).sum()) )
,但是对于两个数组的指定轴?
我打算实现的示例表示:
[(i-j) for i in pos1 for j in pos2]
(所有值均为 [ a 0 0 ] [ x 0 0 ]
A = [ b 0 0 ] ; B = [ y 0 0 ]
[ c 0 0 ] [ z 0 0 ]
[ a-x 0 0 ]
[ a-y 0 0 ]
[ a-z 0 0 ]
[ b-x 0 0 ]
Result = [ b-y 0 0 ]
[ b-z 0 0 ]
[ c-x 0 0 ]
[ c-y 0 0 ]
[ c-z 0 0 ]
,并且将对所有列执行操作。)
答案 0 :(得分:1)
我不确定我是否完全理解你想做什么......如果我有,你可以使用广播做元素差异,见下文
In [24]: a = np.random.random((5,3))
In [25]: b = np.random.random((5,3))
In [26]: c = a[:,None,:]-b
In [27]: c[3,4]
Out[27]: array([ 0.55732535, 0.30270483, 0.48249629])
In [28]: a[3]-b[4]
Out[28]: array([ 0.55732535, 0.30270483, 0.48249629])
In [29]: c[0,3]
Out[29]: array([ 0.28562698, 0.33227255, 0.35890964])
In [30]: a[0]-b[3]
Out[30]: array([ 0.28562698, 0.33227255, 0.35890964])
In [31]: