Python: Elementwise difference for multidimensional array
我试图找到两组粒子之间的最小图像分离。每个集合中大约有40个粒子,它们的位置向量(三维)存储在两个一维数组中。在应用了最小图像准则之后,我必须计算一组中每个粒子和另一组中每个粒子之间的欧几里得距离。为了更清楚地说明这一点,对于坐标为
在三维中,欧几里得距离为
(函数
我正在寻找一种有效的方法来实现这一点,因为作为分析多个数据集的一部分,我必须执行相同的操作,每个数据集大约有20000个时间步,每个时间步包含3组40个粒子,即每个数据集中为每个时间步计算6组组合。
googling让我找到了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | 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 等),从分量阵列中重建(40, 3) 阵列,并重复cdist 。用于计算三维距离
小精灵
计算
除了两个数组的指定轴之外,是否有任何内置的numpy函数可以给出等效的
我想要达到的目标的一个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 | [ 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 ] |
号
(所有值都是
我不确定我完全理解你想做什么…如果有的话,你可以用广播来做元素上的区别,见下面
1 2 3 4 5 6 7 8 9 10 11 12 | 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]: |