【问题标题】:Calculating a distance matrix in Pandas from a list of xyz coordinates从 xyz 坐标列表计算 Pandas 中的距离矩阵
【发布时间】:2018-12-03 17:37:43
【问题描述】:

我有一个 xyz 坐标的 Pandas 数据框,看起来像这样。它不是完整的数据框,只是一个部分

             X         Y         Z
0      [-5.43]  [28.077]  [-0.842]
1     [-3.183]  [26.472]   [1.741]
2     [-2.574]  [22.752]    [1.69]
3     [-1.743]  [21.321]   [5.121]
4      [0.413]  [18.212]   [5.392]
5      [0.714]  [15.803]   [8.332]
6      [4.078]  [15.689]  [10.138]
7      [5.192]    [12.2]   [9.065]
8      [4.088]   [12.79]   [5.475]
9      [5.875]  [16.117]   [4.945]
10     [8.514]  [15.909]    [2.22]
11    [12.235]   [15.85]   [2.943]
12    [13.079]  [16.427]  [-0.719]

每一行对应xyz平面上的一个点,每一列对应该点在空间中的位置。我想用这些数据做的是通过比较每个点来为这些数据创建一个距离矩阵。最简单的方法是什么?

【问题讨论】:

标签: python pandas


【解决方案1】:

首先,直接从每个单元格中的列表中提取元素,而不是使用长度为一的列表:

df = df.applymap(lambda x: x[0])

现在为您的 DataFrame 创建一个笛卡尔积:

df['key'] = 1
v = df.merge(df, on='key').drop('key', 1)

最后,使用numpy.linalg.norm

a, b = np.split(v.values, 2, axis=1)
np.linalg.norm(a-b, axis=1)

array([ 0.        ,  3.78112721,  6.55159408,  9.73626592, 13.05073293,
       16.5094545 , 19.08991902, 21.51870493,
        ...,
        3.80204011, 21.87054435, 19.27190362, 17.05360123, 16.66578891,
       14.17596917, 15.336336  , 14.12221987, 13.25891979, 11.50788799,
        9.1692209 ,  5.45392244,  3.80204011,  0.        ])

这是一个相当消耗内存的解决方案,因为它需要 O(N^2) 内存来创建笛卡尔积。如果这成为问题,您可以创建一个执行相同操作的生成器,但会牺牲一些速度:

def lazy_distance(df):
    a = df.values
    for x in a:
        for y in a:
            yield np.linalg.norm(x - y)

In [78]: np.array_equal(np.array(list(lazy_distance(df))), np.linalg.norm(a-b, axis=1))
Out[78]: True

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-06-09
    • 2013-06-20
    • 2018-08-05
    • 1970-01-01
    • 2020-04-12
    • 2013-12-16
    • 2013-04-14
    相关资源
    最近更新 更多