以矢量化方式查询距离矩阵

时间:2018-07-29 18:54:30

标签: python pandas vectorization

一般的问题是,在给定距离矩阵的情况下,找到列表中每个城市之间然后返回第一个城市的总距离。

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

2 个答案:

答案 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)