【发布时间】:2021-03-15 23:24:03
【问题描述】:
我有以下 2 个数组:
X = array([37., 42., 31., 27., 37.])
Y = array([52., 57., 62., 68., 69.])
我也可以将它们与此组合如下:
XY = np.array((X, Y)).T
产生
([[37., 52.],
[42., 57.],
[31., 62.],
[27., 68.],
[37., 69.]])
我想计算所有点对之间的距离
例如我想这样做:
(
np.linalg.norm(np.array([37, 52]) - np.array([42, 57]))
+ np.linalg.norm(np.array([42, 57]) - np.array([31, 62]))
+ np.linalg.norm(np.array([31, 62]) - np.array([27, 68]))
+ np.linalg.norm(np.array([27, 68]) - np.array([37, 69]))
+ np.linalg.norm(np.array([37, 69]) - np.array([37, 52]))
)
然后产生53.41509195750892
我写了一个这样的函数:
def distance(X, Y):
N = len(X)
T = 0
oldx, oldy = X[-1], Y[-1]
for x, y in zip(X, Y):
T += np.linalg.norm((np.array([x,y])-np.array([oldx,oldy])))
oldx = x
oldy = y
return T
print(distance(X, Y))
还产生53.41509195750891
我很想知道是否有更优雅/更有效的方法来使用 numpy 数组操作来完成此操作。
编辑:对不起,我给的原始示例函数是错误的,现在应该是正确的
编辑:感谢大家的回答!这是我的大小为 50 的数组的基准,似乎 Dani 的答案是最快的,尽管 Akshay 的答案对于大小为 5 的数组更快。
def distance_charel(X, Y):
N = len(X)
T = 0
oldx, oldy = X[-1], Y[-1]
for x, y in zip(X, Y):
T += np.linalg.norm((np.array([x,y])-np.array([oldx,oldy])))
oldx = x
oldy = y
return T
def distance_dani(X, Y):
XY = np.array((X, Y)).T
diff = np.diff(XY, axis=0, prepend=XY[-1].reshape((1, -1)))
ss = np.power(diff, 2).sum(axis=1)
res = np.sqrt(ss).sum()
return res
def distance_akshay(X, Y):
XY = np.array((X, Y)).T
pairwise = pairwise = np.sqrt(np.sum(np.square(np.subtract(XY[:,None,:],XY[None,:,:])), axis=-1))
total = np.sum(np.diag(pairwise,k=1))+pairwise[0,-1]
return total
def distance_gwang(X, Y):
XY = np.array((X, Y)).T
return sum([sum((p1 - p2) ** 2) ** .5 for p1, p2 in zip(XY, XY[1:])])
def distane_andy(X, Y):
arr = np.array((X, Y)).T
return np.linalg.norm(arr - np.roll(arr, -1, axis=0), axis=1).sum()
然后
print(distance_charel(X, Y))
print(distance_dani(X, Y))
print(distance_akshay(X, Y))
print(distance_gwang(X, Y)) # I think it misses the distance between last and first element
print(distane_andy(X, Y))
%timeit distance_charel(X, Y)
%timeit distance_dani(X, Y)
%timeit distance_akshay(X, Y)
%timeit distance_gwang(X, Y)
%timeit distane_andy(X, Y)
输出
2586.769647563161
2586.76964756316
2586.7696475631597
2568.8811037431624
2586.7696475631597
2.49 ms ± 117 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
29.9 µs ± 191 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
385 µs ± 12.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
1.09 ms ± 4.6 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
31.2 µs ± 133 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
编辑:我现在接受了 Dani 的回答,因为我发现他的代码最适合我的情况(使用 numpy 向量运算,可读性强,速度最快(小幅度))。感谢大家的回答!
编辑:我更新了基准,使用280 coordinates
【问题讨论】:
-
你想计算索引 0 对 1,2,3,4... 然后索引 1 对 2,3,4... 或者只是你在第二行写第一个的方式,第二排第三排等等。
-
我写的方式,先写第二,再写第二,等等,最后再写第一
-
你没有更新 oldx,oldy 所以这会用最后一个来计算
-
是的,现在已经修复了,原来的功能搞砸了......
-
检查我的矢量化解决方案和比较其他答案的基准。
标签: python numpy scipy vectorization distance