Вычисление матрицы расстояний в Пандах из списка координат XYZ - PullRequest
0 голосов
/ 03 декабря 2018

У меня есть Pandas dataframe с координатами XYZ, который выглядит следующим образом.Это не полный фрейм данных, а только сечение

             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, а каждый столбец соответствует положению этой точки в пространстве.Что я хотел бы сделать с этими данными, так это создать матрицу расстояний для этих данных, сравнивая каждую точку друг с другом.Что было бы самым простым способом сделать это?

1 Ответ

0 голосов
/ 03 декабря 2018

Сначала извлеките элементы непосредственно из списков в каждой ячейке, а не используйте списки длины один:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...