2014-07-11 3 views
0

Я хотел бы привязать отдельные точки к другим точкам в зависимости от их расстояния в 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") 

ответ

0

Я бы поставил критерии (расстояние, «southness», «westness») в dataframe, а затем отсортировать этот dataframe вдоль этих критериев :

# 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 
0

Это возможно с помощью 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) 
0

Вы также можете попробовать 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 
Смежные вопросы