【问题标题】:Get closest point based on coordinates根据坐标获取最近点
【发布时间】:2014-07-11 09:39:51
【问题描述】:

我想根据它们在 R 中的距离将单个点捕捉到其他点。 详细地说,我有一堆由 X 和 Y 坐标对定义的点。 另外我有一个不同的点,我想捕捉到 最近的邻居(欧几里得距离)。

# target points
df <- data.frame(X=c(1,2,2,2,3,4),Y=c(1,2,2,3,3,4))

# points that need snapping
point1 <- data.frame(X=2.1, Y=2.3)
point2 <- data.frame(X=2.5, Y=2.5)


plot(df)
points(point1$X,point1$Y,pch=20,col="red")
points(point2$X,point2$Y,pch=20,col="blue")

但是如何进行点的捕捉呢? 如何捕捉点并将新的坐标对分配给单个点? R中有一个简单的函数吗?还是我需要申请 dist() 函数获取距离矩阵并搜索 最近的距离?也许有更直接的方法。

它应该是这样的:

1) 捕捉到最近的(欧式距离)点(点 1 的清晰解)

point1$X_snap <- 2
point1$Y_snap <- 2

2) 如果两个或多个点相似地接近于 捕捉到更“东北”的地方 a)首先捕捉到更北的那个(Y方向) b) 如果有不止一个在 Y 方向上相似距离的捕捉 到更东边的那个

point2$X_snap <- 3
point2$Y_snap <- 3

对于结果应该是什么样子的图形说明

#plot snapped points:
points(point1$X_snap,point1$Y_snap,pch=8,col="red")
points(point2$X_snap,point2$Y_snap,pch=8,col="blue")

【问题讨论】:

    标签: r coordinates distance euclidean-distance


    【解决方案1】:

    可以使用dist:

     dist(rbind(point1,df))
              1         2         3         4         5
    2 1.7029386                                        
    3 0.3162278 1.4142136                              
    4 0.3162278 1.4142136 0.0000000                    
    5 0.7071068 2.2360680 1.0000000 1.0000000          
    6 1.1401754 2.8284271 1.4142136 1.4142136 1.0000000
    7 2.5495098 4.2426407 2.8284271 2.8284271 2.2360680
              6
    2          
    3          
    4          
    5          
    6          
    7 1.4142136
    

    因此,第一列中具有最小值(距离)的行标识了df 中最接近point1 的点。在您的示例中,您有一个重复的位置。对每个 point_x 重复此操作。

    【讨论】:

      【解决方案2】:

      我找到了另一个使用 matchpt() 函数的解决方案 来自 Biobase(Bioconductor):

      # target points
      df <- data.frame(X=c(1,2,2,2,3,4),Y=c(1,2,2,3,3,4))
      
      # points that need snapping
      point1 <- data.frame(X=2.1, Y=2.3)
      point2 <- data.frame(X=2.5, Y=2.5)
      
      snap <- function(df,point){
        require(Biobase)
        d <- matchpt(as.matrix(df),
                     as.matrix(data.frame(X=point$X+0.0001,Y=point$Y+0.0001))) # to the "northwest" criteria correct
      
        min_row <- as.numeric(rownames(d[d$distance==min(d$distance),]))
      
        point$X_snap <- unique(df[min_row,"X"])
        point$Y_snap <- unique(df[min_row,"Y"])
      
        point
      }
      
      snap(df,point2)
      

      【讨论】:

        【解决方案3】:

        您可能还想尝试使用RANN package 进行快速最近邻搜索:

        # your data
        df <- data.frame(X=c(1,2,2,2,3,4),Y=c(1,2,2,3,3,4))
        pts <- data.frame(X=c(2.1, 2.5), Y=c(2.3, 2.5))
        library(RANN)
        # for each point in pts, find the nearest neighbor from df
        closest <- RANN::nn2(data = df, query = pts, k = 1)
        # argument k sets the number of nearest neighbours, here 1 (the closest)
        closest
        # $nn.idx
        # [,1]
        # [1,]    3
        # [2,]    5
        # 
        # $nn.dists
        # [,1]
        # [1,] 0.3162278
        # [2,] 0.7071068
        # Get coordinates of nearest neighbor
        pts$X_snap <- df[closest$nn.idx, "X"]
        pts$Y_snap <- df[closest$nn.idx, "Y"]
        pts
        #     X   Y X_snap Y_snap
        # 1 2.1 2.3      2      2
        # 2 2.5 2.5      3      3
        

        【讨论】:

          【解决方案4】:

          我会将标准(距离、“南”、“西”)放入数据框中,然后按照这些标准对该数据框进行排序:

          # input data
          df <- data.frame(X=c(1,2,2,2,3,4),Y=c(1,2,2,3,3,4))
          point1 <- data.frame(X=2.1, Y=2.3)
          point2 <- data.frame(X=2.5, Y=2.5)
          df.res[with(df.res, order(dst, dy, dx)), ]
          
          # function that sorts all potential snapping points according to distance, "westness", "southness"
          snap.xy <- function(point, other.points) {
            df.res <- data.frame(X = other.points$X,   # to later access the coordinates to snap to
                                 Y = other.points$Y,   # dto
                                 dx <- point$X - other.points$X, # "westness" (the higher, the more "west")
                                 dy <- point$Y - other.points$Y, # "southness"
                                 dst = sqrt(dx^2 + dy^2))        # distance
            # print(df.res[with(df.res, order(dst, dy, dx)), ])  # just for checking the results
            return(df.res[with(df.res, order(dst, dy, dx)), ][1,c("X", "Y")])  # return only the X/Y coordinates
          }
          
          # examples
          snap.xy(point1, df)    # 2/2
          snap.xy(point2, df)    # 3/3
          snap.xy(point2, df)$X  # 3
          snap.xy(point2, df)$Y  # 3
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2017-06-21
            • 1970-01-01
            • 2020-05-27
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多