测量到最近一组点的距离-python

测量到最近一组点的距离-python,python,pandas,spatial,kdtree,Python,Pandas,Spatial,Kdtree,我试图测量每个点到最近点组的最短欧几里德距离。使用下面的方法,我在两个不同的时间点在x,y中显示了6个独特的点。我在x\u-ref,y\u-ref中记录了一个单独的xy点,我在其中传递一个半径。所以对于这个半径外的每个点,我想找到到半径内任何点的最短距离。对于半径内的点,只需返回0 计算距离测量每个特定点与其余点之间的距离。我希望返回到半径内最近点的距离 import pandas as pd import numpy as np import matplotlib.pyplot as plt

我试图测量每个点到最近点组的最短欧几里德距离。使用下面的方法,我在两个不同的时间点在
x,y
中显示了6个独特的点。我在
x\u-ref,y\u-ref
中记录了一个单独的xy点,我在其中传递一个半径。所以对于这个半径外的每个点,我想找到到半径内任何点的最短距离。对于半径内的点,只需返回0

计算距离
测量每个特定点与其余点之间的距离。我希望返回到半径内最近点的距离

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from scipy.spatial.distance import pdist, squareform

df = pd.DataFrame({        
    'Time' : [1,1,1,1,1,1,2,2,2,2,2,2],                               
    'Item' : ['A','B','C','D','E','F','A','B','C','D','E','F'],      
    'x' : [5,5,8,3,6,2,6,7,4,2,7,6],
    'y' : [-2,0,-2,0,0,4,-1,2,-3,4,-4,2],     
    'x_ref' : [4,4,4,4,4,4,4,4,4,4,4,4],
    'y_ref' : [-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2],                          
    })

# Determine square distance
square_dist = (df['x_ref'] - df['x']) ** 2 + (df['y_ref'] - df['y']) ** 2
              
# Return df of items within radius
inside_radius = df[square_dist <= 3 ** 2].copy()

def calculate_distances(df):

    id_distances = pd.DataFrame(
        squareform(pdist(df[['x','y']].to_numpy())),  
        columns = df['Item'],
        index = df['Item'],
    )

    return id_distances

df_distances = df.groupby(['Time']).apply(calculate_distances).reset_index()

这里有一种使用方法,当您打算进行许多距离和邻居搜索时,它非常有用

将numpy导入为np
作为pd进口熊猫
从scipy.spatial导入KDTree
半径范围内的定义(z,半径,闭合=假):
中心=z['x_-ref','y_-ref']].mean()#它们都应该是相同的
z=z['x','y']]
距离=半径*1.0001(如果闭合),否则半径
dist,idx=KDTree(z).query(
中心,k=无,距离(上限=距离)
如果关闭:
idx=[如果d>>df.assign(distance=df.groupby('Time',group\u keys=False),则i代表d,i在zip中(dist,idx)。应用(
…在半径范围内(距离,半径=3,闭合=真)
时间项x y x_参考y_参考距离
01A 5-23-20.000000
1 B 5 0 3-2 0.000000
21c8-23-23000000
31D303-2000000
4 1 E 6 0 3-2 1.000000
5 1 F 2 4 3-2 4.123106
62a 6-14-200.000000
72B724-23162278
82 C4-34-200.000000
92D2444-26403124
102E7-443.162278
11 2 F 6 2 4-23.000000
说明:

  • groupby('Time')
    确保按时间将函数
    应用于每个组
  • 在函数内部,第一个
    KDTree
    查询查找以
    (x\u ref,y\u ref)
    为中心的给定半径的球体(这里是圆,因为这个问题是2D的,但这可以推广到nD)内的点
  • 由于
    distance\u upper\u bound
    参数是独占的(即
    KDTree
    查询只返回严格小于此值的距离),如果我们希望在半径处包含点(当
    closed=True
    时),那么我们需要做一些额外的处理:向半径添加一小部分,然后剪裁
  • 还请注意,默认情况下,使用
    p=2
    范数(欧几里德范数),但也可以使用其他范数
  • 内是球体内的这些点
  • (注意:如果没有这样的点,我们将返回所有距离的
    NaN
  • 第二个
    KDTree
    查询查找所有点(组内)到
    点的最近距离。这方便地返回球体内点的
    0
    (因为这是到自身的距离)其他点到最近点的距离,这就是我们的结果
  • 我们将结果作为一个
    系列
    返回,这样熊猫们就知道如何正确地将其设置,并最终将其指定给一个名为
    'distance'
    的列
  • 最后一点观察:原始问题中提供的预期结果似乎忽略了
    x\u ref,y\u ref
    ,并使用单个
    中心=(4,-2)
    。在第一组(
    Time==1
    )中,
    C
    的正确距离为3.0(到a的距离),并且
    E
    不在圆圈内

    补充

    如果您还想捕获每个点的最近邻:

    def in_radius_dist(z,radius,closed=False):
    中心=z['x_-ref','y_-ref']].mean()#它们都应该是相同的
    z=z['x','y']]
    距离=半径*1.0001(如果闭合),否则半径
    dist,idx=KDTree(z).query(
    中心,k=无,距离(上限=距离)
    如果关闭:
    
    idx=[i代表d,i在zip中(距离,idx)如果d,半径是多少?定义在哪里?修改。半径内的点记录在
    半径内
    时间列定义了一个组,对吗?这里我正确吗:对于每个组(时间),我们计算2列。(1)它是从参考点算起的半径吗,(2)到参考点半径内最近点的距离。有了这个,一个简单的if-else可以计算出你想要的列谢谢@Pierre D。很好的解释。
    
        Time Item  x  y  x_ref  y_ref  distance
    0      1    A  5 -2      3     -2  0.000000 # within radius 0
    1      1    B  5  0      3     -2  0.000000 # within radius 0
    2      1    C  8 -2      3     -2  2.828427 # nearest within radius is E
    3      1    D  3  0      3     -2  0.000000 # within radius 0
    4      1    E  6  0      3     -2  0.000000 # within radius 0
    5      1    F  2  4      3     -2  4.123106 # nearest within radius is D
    6      2    A  6 -1      4     -2  0.000000 # within radius 0
    7      2    B  7  2      4     -2  3.162278 # nearest within radius is A
    8      2    C  4 -3      4     -2  0.000000 # within radius 0
    9      2    D  2  4      4     -2  6.403124 # nearest within radius is A
    10     2    E  7 -4      4     -2  3.162278 # nearest within radius is C or A
    11     2    F  6  2      4     -2  3.000000 # nearest within radius is A