【问题标题】:KDTree duplicating rowsKDTree 复制行
【发布时间】:2021-12-21 02:55:25
【问题描述】:

我有两个数据框。

  1. 第一个数据帧 (map) 由两列组成:“X”和“Y”。 map 是 83150 行。
  2. 第二个数据框 (cords) 由两列组成:“X 旋转”和“Y 旋转”。 coords 是 2702 行。

目标是为map 内的每个 (X,Y) 坐标找到与coords 内的 (X Rotate, Y Rotate) 坐标最近的邻居。

为了做到这一点,由于 83150/2702,我将 coords 内的每一行复制了 31 次。现在,coords 有 83762 行。这意味着每个 (X,Y) 坐标都将找到它与 (X Rotate, Y Rotate) 的最近邻,coords 内将有 612 个坐标没有最近邻匹配。

这是实现这一点的函数:

def nearest_neighbors(df, map):
    num_pts = math.ceil(map.shape[0] / df.shape[0])
    map = map[["X", "Y"]].to_numpy()
    duplicate_cords_df = pd.DataFrame(np.repeat(df.values, num_pts, axis=0), columns=df.columns)
    duplicate_cords_sub = duplicate_cords_df[["X Rotate", "Y Rotate"]].to_numpy()
    duplicate_cords_sub = duplicate_cords_sub.to_numpy()
    list_of_dicts = []
    for row in map:
        map_tree = spatial.cKDTree(duplicate_cords_sub)
        distance, index = map_tree.query(row)
        cols = ["Map X", "Map Y", "X Rotate", "Y Rotate", "Distance"]
        map_x = row[0]
        map_y = row[1]
        coords_x = (duplicate_cords_sub[index]).flat[0]
        coords_y = (duplicate_cords_sub[index]).flat[1]
        results = [map_x, map_y, coords_x, coords_y, distance]
        results_dict = dict(zip(cols, results))
        list_of_dicts.append(results_dict)
    results_df = pd.DataFrame(list_of_dicts)
    return results_df

但是,当我检查 results_df 中的重复数时,我注意到每个 (X Rotate, Y Rotate) 坐标的使用次数都不同。

overall_df_dup = results_df.groupby(['X Rotate', 'Y Rotate']).size().reset_index(name='count')
print(overall_df_dup)

                X Rotate           Y Rotate   count
0                -74.25               0.00     16
1                -72.48             -12.37     28
2                -72.48              -8.84     37
3                -72.48              -5.30     43
4                -72.48              -1.77     39
...                 ...                ...    ...
2697              70.71              14.14     62
2698              72.48              -8.84     45
2699              72.48              -1.77     55
2700              72.48               1.77     47
2701              72.48               5.30     48

我检查了提供给 KDTree 函数的数据帧的重复计数,它是正确的:

coords_dup = duplicate_cords.groupby(['X Rotate', 'Y Rotate']).size().reset_index(name='count')
print(coords_dup)

                 X Rotate           Y Rotate  count
0                -74.25              -0.00     31
1                -72.48             -12.37     31
2                -72.48              -8.84     31
3                -72.48              -5.30     31
4                -72.48              -1.77     31
...                 ...                ...    ...
2697              70.71              14.14     31
2698              72.48              -8.84     31
2699              72.48              -1.77     31
2700              72.48               1.77     31
2701              72.48               5.30     31

生成的 df 如何包含比输入 KdTree 函数的原始数据框中更多的坐标重复项?

额外问题:是否可以将每个 (X Rotate, Y Rotate) 坐标映射到 30 次,而仅将一些 (X Rotate, Y Rotate) 映射到 31 次?理想情况下,我希望每个 (X Rotate, Y Rotate) 坐标都映射到 30 次。

【问题讨论】:

  • 为什么要在 coords 数据帧上重复行?
  • map 数据帧的长度是 coords 数据帧的约 31 倍。所以我将coords 中的行复制了31 次,这样map 中的每个坐标对都可以映射到coords 中的最近邻坐标对。
  • 如果我不正确地进行这个复制过程,那么我可以改变我的方法。这正是我认为有意义的事情。
  • 我希望每个 (X Rotate, Y Rotate) 坐标映射到 30 次,并且只有一些 (X Rotate, Y Rotate) 映射到 31 次。理想情况下,我希望每个 (X Rotate, Y Rotate) 坐标都映射到 30 次。这就是为什么我想复制coords 31 次。
  • (X Rotate1, Y Rotate1) 将始终匹配相同的 (X, Y),不是吗?

标签: python pandas kdtree


【解决方案1】:

一开始可能不是正确的答案,但这有助于使用KDTree

创建一个最小的可重现示例:

import pandas as pd
import numpy as np
from scipy.spatial import cKDTree

gen_coords = lambda s: np.round(np.random.randint(-100, 100, s) \
                                + np.random.random(s), 2)

df_map = pd.DataFrame(gen_coords((83150, 2)), columns=['X', 'Y'])
df_coords = pd.DataFrame(gen_coords((2702, 2)), columns=['X Rotate', 'Y Rotate'])

地图坐标:

df_coords['IDX'] = cKDTree(df_map).query(df_coords, k=30)[1].tolist()
df_coords = df_coords.explode('IDX')
df_coords[['X', 'Y']] = df_map.loc[df_coords['IDX'].tolist()].values
df_coords = df_coords.drop(columns='IDX')

输出结果:

>>> df_coords

      X Rotate  Y Rotate      X      Y
0        99.00     57.35  99.18  57.13
0        99.00     57.35  98.54  57.53
0        99.00     57.35  99.14  58.20
0        99.00     57.35  99.88  57.36
0        99.00     57.35  98.03  56.94
...        ...       ...    ...    ...
2701     92.75     -8.69  91.40  -9.74
2701     92.75     -8.69  91.75  -7.29
2701     92.75     -8.69  93.41  -7.09
2701     92.75     -8.69  94.48  -8.78
2701     92.75     -8.69  93.29 -10.36

[81060 rows x 4 columns]

>>> df_coords.value_counts(['X Rotate', 'Y Rotate'])
X Rotate  Y Rotate
-99.71    -20.20      30
 35.72     85.56      30
 34.64     76.37      30
 34.76     8.32       30
 34.90    -4.75       30
                      ..
-32.69    -44.76      30
-32.66     72.96      30
-32.63    -40.65      30
-32.61     34.91      30
 99.89     98.02      30
Length: 2702, dtype: int64

【讨论】:

    猜你喜欢
    • 2011-06-05
    • 1970-01-01
    • 2020-10-22
    • 1970-01-01
    • 2017-01-09
    • 1970-01-01
    • 2018-06-16
    • 2010-09-20
    • 2016-02-17
    相关资源
    最近更新 更多