Find the Nearest X,Y Coordinate Using R

Find the nearest X,Y coordinate using R

Here's one way, using the RANN package. The approach is similar to that shown in this post, but is adapted for a single set of points (the linked post was about finding the nearest point in set A to each point in set B).

xy <- read.table(text='point x         y
1 1601774 14544454
2 1616574 14579422
3 1608698 14572922
4 1602948 14572990
5 1607355 14573871
6 1615336 14578178
7 1603398 14574495
8 1605153 14570727
9 1606758 14573845
10 1606655 14570953', header=TRUE, row.names=1)

library(RANN)
closest <- nn2(data=xy, k=2)[[1]]

Above, we supply your single set of points, xy, to the data argument, and specify that we want nn2 to find the two nearest points to each point (because the nearest point is the focal point itself). The nn2 function returns a list with two elements: a vector (matrix, in this case) of indices of each of the k nearest points (for each queried point); and a vector (matrix) of the distances. I'm assuming we're not interested in the distances, so above we subset the result to the first element.

For our problem, the result is a two-column matrix giving the index of the queried point in the first column and the index of the nearest point in the second.

closest

## [,1] [,2]
## [1,] 1 8
## [2,] 2 6
## [3,] 3 5
## [4,] 4 7
## [5,] 5 9
## [6,] 6 2
## [7,] 7 4
## [8,] 8 10
## [9,] 9 5
## [10,] 10 8

To get a matrix of coordinates of the nearest points, you could use:

xy[closest[, 2], ]

By default nn2 uses a kd tree - you might want to experiment with treetype='bd'.

Find nearest X,Y coordinate within another list of coordinates in R

You could just use the actual distance formula, e.g.

library(dplyr)

Coords %>% rowwise() %>%
mutate(min_dist = min(sqrt((X - OutsideLines$X) ^ 2 + (Y - OutsideLines$Y) ^ 2)))

#> Source: local data frame [6 x 5]
#> Groups: <by row>
#>
#> # A tibble: 6 × 5
#> Tag Animal X Y min_dist
#> <int> <int> <dbl> <dbl> <dbl>
#> 1 228 1 -18.226 26.720 8.182184
#> 2 232 2 -18.268 7.558 11.947343
#> 3 233 3 -18.274 -2.041 21.370347
#> 4 307 4 -7.975 -61.421 80.780573
#> 5 241 5 8.052 -61.364 83.525871
#> 6 243 6 18.196 -2.118 38.831923

finding the closest XY coordinates in a large dataframe to reference coordinates in another dataframe in R

step-1

we can calculate the distances between each df1 and df2 using the following code

df1 <- data.frame(X = c(7.48, 7.82, 8.15, 8.47, 8.80, 9.20, 9.51, 9.83, 10.13, 10.59, 7.59, 8.06, 8.39, 8.87, 9.26, 9.64, 10.09, 10.48, 10.88, 11.45), 
Y = c(49.16, 48.78, 48.40, 48.03, 47.65, 47.24, 46.87, 46.51, 46.15, 45.73, 48.70, 48.18, 47.72, 47.20, 46.71, 46.23, 45.72, 45.24, 44.77, 44.23),
ID = c("B_1", "B_1", "B_1", "B_1", "B_1", "B_1", "B_1", "B_1", "B_1", "B_1", "B_1_2", "B_1_2", "B_1_2", "B_1_2", "B_1_2", "B_1_2", "B_1_2", "B_1_2", "B_1_2", "B_1_2"),
TI = c(191.31, 191.35, 191.39, 191.44, 191.48, 191.52, 191.56, 191.60, 191.64, 191.69, 1349.93, 1349.97, 1350.01, 1350.05, 1350.09, 1350.14, 1350.18, 1350.22, 1350.26, 1350.30))

df2 <- data.frame(X = c(7.62, 8.25, 8.95, 9.71, 10.23),
Y = c(49.06, 48.30, 47.55, 46.77, 46.25))

Azimuth <- data.frame(0)
for (i in 1:nrow(df2)){
for (j in 1:nrow(df1)){
Azimuth[j,i] = sqrt((df2[i,1]-df1[j,1])^2+(df2[i,2]-df1[j,2])^2)
}}

then we can combine df1 data frame and Azimuth using the following code

df1 <- data.frame(df1,Azimuth)

step-2

[to get the desired output, we got the answer from the "akrun"]
https://stackoverflow.com/questions/65345208/how-to-subset-rows-in-specific-columns-based-on-minimum-values-in-individual-col[1]

the code is as follows

library(dplyr)
library(purrr)
nm1 <- names(df1)[5:6]
map_dfr(nm1, ~ df1 %>%
group_by(ID) %>%
slice_min(!! rlang::sym(.x))) %>%
ungroup %>%
mutate(d = select(., all_of(nm1)) %>% reduce(pmin))

Finding closest coordinates between two large data sets

I wrote up an answer referencing this thread. The function is modified to take care of reporting the distance and avoid hard-coding. Please note that it calculates Euclidean distance.

library(data.table)
#Euclidean distance
mydist <- function(a, b, df1, x, y){

dt <- data.table(sqrt((df1[[x]]-a)^2 + (df1[[y]]-b)^2))

return(data.table(Closest.V1 = which.min(dt$V1),
Distance = dt[which.min(dt$V1)]))
}

setDT(df1)[, j = mydist(HIGH_PRCN_LAT, HIGH_PRCN_LON, setDT(df2),
"HIGH_PRCN_LAT", "HIGH_PRCN_LON"),
by = list(id, HIGH_PRCN_LAT, HIGH_PRCN_LON)]
  #     id HIGH_PRCN_LAT HIGH_PRCN_LON Closest.V1 Distance.V1
# 1: 1 52.88144 -2.873778 5 0.7990743
# 2: 2 57.80945 -2.234544 8 2.1676868
# 3: 4 34.02335 -3.098445 10 1.4758202
# 4: 5 63.80879 -2.439163 3 4.2415854
# 5: 6 53.68881 -7.396112 2 3.6445416
# 6: 7 63.44628 -5.162345 3 2.3577811
# 7: 8 21.60755 -8.633113 9 8.2123762
# 8: 9 78.32444 3.813290 7 11.4936496
# 9: 10 66.85533 -3.994326 1 1.9296370
# 10: 3 51.62354 -8.906553 2 3.2180026

You can use RANN::nn2, but you need to make sure to use the right syntax. Following works!

as.data.frame(RANN::nn2(df2[,c(2,3)],df1[,c(2,3)],k=1))
#    nn.idx   nn.dists
# 1 5 0.7990743
# 2 8 2.1676868
# 3 10 1.4758202
# 4 3 4.2415854
# 5 2 3.6445416
# 6 3 2.3577811
# 7 9 8.2123762
# 8 7 11.4936496
# 9 1 1.9296370
# 10 2 3.2180026

Find nearest 3 points to a given point in a dataframe

dists <- geosphere::distHaversine(dat[dat$set=="point",c("y","x")], dat[,c("y","x")])
dists
# [1] 123339.4 151513.9 153862.4 0.0 111319.5 505814.4
dat$set[dat$set != "point" & rank(dists) < 5] <- "closest"
dat
# x y set
# 1 61 -112 closest
# 2 63 -113 closest
# 3 61 -113
# 4 62 -111 point
# 5 61 -111 closest
# 6 64 -120

The reason we use < 5 is that the own-distance (point to point) will be the closest (0), so we need ranks 2-4. This assumes there is one "point"; if there are more, you'll likely want outer (to produce a matrix of distances) and look at each row before populating $set.

I'm inferring latitude and longitude from the sp tag, so chose the Haversine distance calculation since it's fast, and the appearance of coarse coordinates does not suggest the requirement for sub-millimeter accuracy (i.e., Vincenty Ellipsoid formula). There are other distance calculations if needed.

Find nearest points of latitude and longitude from different data sets with different length

Here is an other possible solution:

library(rgeos)
set1sp <- SpatialPoints(set1)
set2sp <- SpatialPoints(set2)
set1$nearest_in_set2 <- apply(gDistance(set1sp, set2sp, byid=TRUE), 1, which.min)

head(set1)
lon lat nearest_in_set2
## 1 13.67111 48.39167 10
## 2 12.86695 48.14806 10
## 3 15.94223 48.72111 10
## 4 11.09974 47.18917 1
## 5 12.95834 47.05444 1
## 6 14.20389 47.12917 1

Find the nearest points from one data.frame in another data.frame

You can use the get.knnx function from the FNN package:

set.seed(123)
library(data.table)
a <- data.table(x = runif(10), y = runif(10))
b <- data.table(x = runif(30), y = runif(30))

library(FNN)
c<-get.knnx(b,a,k=1)

a$b.x <- b$x[c$nn.index]
a$b.y <- b$y[c$nn.index]

a

x y b.x b.y
1: 0.2875775 0.95683335 0.28915974 0.89504536
2: 0.7883051 0.45333416 0.69280341 0.44220007
3: 0.4089769 0.67757064 0.41372433 0.71018240
4: 0.8830174 0.57263340 0.96302423 0.66511519
5: 0.9404673 0.10292468 0.90229905 0.09484066
6: 0.0455565 0.89982497 0.02461368 0.81464004
7: 0.5281055 0.24608773 0.54406602 0.12753165
8: 0.8924190 0.04205953 0.88953932 0.04583117
9: 0.5514350 0.32792072 0.47779597 0.44851634
10: 0.4566147 0.95450365 0.28915974 0.89504536


Related Topics



Leave a reply



Submit