一般的问题是,在给定距离矩阵的情况下,找到列表中每个城市之间然后返回第一个城市的总距离。
An example的距离矩阵。
以下是该问题的可行解决方案,但是我不确定如何将其转换为矢量化解决方案。 “矩阵”是一个熊猫数据框,其中包含距离矩阵,而城市是一个城市列表。
import pandas as pd
def total_distance(matrix, cities):
dist = matrix[cities[0]][cities[-1]]
i = 0
while i < len(cities)-1:
dist += matrix[cities[i]][cities[i+1]]
i+=1
return dist
答案 0 :(得分:2)
如果df
是您的距离矩阵,则先将其堆叠。只需执行一次,因为这是一项昂贵的操作。
dfstacked = df.stack()
接下来,以矢量化方式计算距离:
dfstacked.loc[list(zip(cities, np.roll(cities, -1)))].sum()
MWE:
df
A B C D
A 0 5 5 3
B 5 0 5 2
C 5 5 0 4
D 3 2 4 0
cities = ['A', 'D', 'B']
dfstacked = df.stack()
dfstacked.loc[list(zip(cities, np.roll(cities, -1)))].sum()
10 # 3 + 2 + 5
答案 1 :(得分:1)
从Coldspeed的一个很好的答案中得出的结论,在使用numpy.trace
之前,我们可以仅沿两个维度进行索引就可以避免堆叠。
np.trace(df.loc[cities, np.roll(cities, -1)])
这可能会更快一些,里程当然会随您输入的大小而变化。
演示
import pandas as pd
import numpy as np
df = pd.DataFrame(np.random.randint(0, 100, (25, 25)))
cities = np.random.randint(0, 25, 10).tolist()
%timeit np.trace(df.loc[cities, np.roll(cities, -1)])
# 843 µs ± 27 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit df.stack().loc[list(zip(cities, np.roll(cities, -1)))].sum()
# 4.01 ms ± 189 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%%timeit stacked = df.stack()
stacked.loc[list(zip(cities, np.roll(cities, -1)))].sum()
# 2.83 ms ± 7.79 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)