R - Поиск ближайшей соседней точки и числа соседей в заданном радиусе, координаты lat-long

Я пытаюсь понять, как изолированные определенные точки находятся в моем наборе данных. Я использую два метода для определения изоляции, расстояния ближайшего соседа и количества соседних сайтов в пределах заданного радиуса. Все мои координаты находятся в широте и долготе.

Вот как выглядят мои данные:

    pond            lat         long        area    canopy  avg.depth   neighbor    n.lat   n.long  n.distance  n.area  n.canopy    n.depth n.avg.depth radius1500
    A10             41.95928    -72.14605   1500    66      60.61538462                                 
    AA006           41.96431    -72.121     250     0       57.77777778                                 
    Blacksmith      41.95508    -72.123803  361     77      71.3125                                 
    Borrow.Pit.1    41.95601    -72.15419   0       0       41.44444444                                 
    Borrow.Pit.2    41.95571    -72.15413   0       0       37.7                                    
    Borrow.Pit.3    41.95546    -72.15375   0       0       29.22222222                                 
    Boulder         41.918223   -72.14978   1392    98      43.53333333                                 

Я хочу поместить имя ближайшего соседнего пруда в соседний столбец, его lat и long в n.lat и n.long, расстояние между двумя прудами в n.distance и площадь, навес и avg.depth в каждом из соответствующих столбцов.

Во-вторых, я хочу поставить количество прудов в пределах 1500 м от целевого пруда на радиус1500.

Кто-нибудь знает о функции или пакете, которые помогут мне рассчитать расстояния/цифры, которые я хочу? Если это проблема, нетрудно ввести другие данные, которые мне нужны, но имя ближайшего соседа и расстояние, а также количество прудов в пределах 1500 м - это то, что мне действительно нужно.

Спасибо.

Ответы

Ответ 1

Наилучшим вариантом является использование библиотек sp и rgeos, которые позволяют вам создавать пространственные классы и выполнять геообработку.

library(sp)
library(rgeos)

Прочитайте данные и преобразуйте их в пространственные объекты:

mydata <- read.delim('d:/temp/testfile.txt', header=T)

sp.mydata <- mydata
coordinates(sp.mydata) <- ~long+lat

class(sp.mydata)
[1] "SpatialPointsDataFrame"
attr(,"package")
[1] "sp"

Теперь вычислим попарные расстояния между точками

d <- gDistance(sp.mydata, byid=T)

Найдите второе кратчайшее расстояние (самое близкое расстояние указывает на себя, поэтому используйте второй самый короткий)

min.d <- apply(d, 1, function(x) order(x, decreasing=F)[2])

Построить новый кадр данных с требуемыми переменными

newdata <- cbind(mydata, mydata[min.d,], apply(d, 1, function(x) sort(x, decreasing=F)[2]))

colnames(newdata) <- c(colnames(mydata), 'neighbor', 'n.lat', 'n.long', 'n.area', 'n.canopy', 'n.avg.depth', 'distance')

newdata
            pond      lat      long area canopy avg.depth     neighbor    n.lat    n.long n.area n.canopy n.avg.depth
6            A10 41.95928 -72.14605 1500     66  60.61538 Borrow.Pit.3 41.95546 -72.15375      0        0    29.22222
3          AA006 41.96431 -72.12100  250      0  57.77778   Blacksmith 41.95508 -72.12380    361       77    71.31250
2     Blacksmith 41.95508 -72.12380  361     77  71.31250        AA006 41.96431 -72.12100    250        0    57.77778
5   Borrow.Pit.1 41.95601 -72.15419    0      0  41.44444 Borrow.Pit.2 41.95571 -72.15413      0        0    37.70000
4   Borrow.Pit.2 41.95571 -72.15413    0      0  37.70000 Borrow.Pit.1 41.95601 -72.15419      0        0    41.44444
5.1 Borrow.Pit.3 41.95546 -72.15375    0      0  29.22222 Borrow.Pit.2 41.95571 -72.15413      0        0    37.70000
6.1      Boulder 41.91822 -72.14978 1392     98  43.53333 Borrow.Pit.3 41.95546 -72.15375      0        0    29.22222
        distance
6   0.0085954872
3   0.0096462277
2   0.0096462277
5   0.0003059412
4   0.0003059412
5.1 0.0004548626
6.1 0.0374480316

Изменить:, если координаты находятся в градусах и вы хотите рассчитать расстояние в километрах, используйте пакет geosphere

library(geosphere)

d <- distm(sp.mydata)

# rest is the same

Это должно обеспечить лучшие результаты, если точки разбросаны по всему миру, а координаты находятся в градусах

Ответ 2

Решение, предлагаемое @Zbynek, довольно приятно, но если вы ищете расстояние между двумя соседями в км, как я, я предлагаю это решение.

   earth.dist<-function(lat1,long1,lat2,long2){

           rad <- pi/180
           a1 <- lat1 * rad
           a2 <- long1 * rad
           b1 <- lat2 * rad
           b2 <- long2 * rad
           dlat <- b1-a1
           dlon<- b2-a2
           a <- (sin(dlat/2))^2 +cos(a1)*cos(b1)*(sin(dlon/2))^2
           c <- 2*atan2(sqrt(a),sqrt(1-a))
           R <- 6378.145
           dist <- R *c
           return(dist)
           }


    Dist <- matrix(0,ncol=length(mydata),nrow=length(mydata.sp))

  for (i in 1:length(mydata)){
      for(j in 1:length(mydata.sp)){
          Dist[i,j] <- earth.dist(mydata$lat[i],mydata$long[i],mydata.sp$lat[j],mydata.sp$long[j])
 }}



     DDD <- matrix(0, ncol=5,nrow=ncol(Dist))   ### RECTIFY the nb of col by the number of variable you want

   for(i in 1:ncol(Dist)){
       sub<- sort(Dist[,i])[2]
       DDD[i,1] <- names(sub) 
       DDD[i,2] <- sub
       DDD[i,3] <- rownames(Dist)[i]
       sub_neig_atr <- Coord[Coord$ID==names(sub),]
       DDD[i,4] <- sub_neig_atr$area
       DDD[i,5] <- sub_neig_atr$canopy
       ### Your can add any variable you want here 

   }

    DDD <- as.data.frame(DDD)

    names(DDD)<-c("neigboor_ID","distance","pond","n.area","n.canopy")
   data <- merge(mydata,DDD, by="pond")

В итоге вы получите расстояние в км, если ваши координаты длинны и лат.

Любые предложения, чтобы сделать его лучше?