web-dev-qa-db-ja.com

R-指定された半径内で最も近い隣接点と隣接数を見つける、緯度経度の座標

データセット内で特定のポイントがどのように孤立しているかを把握しようとしています。分離を判断するために、特定の半径内の最も近い隣接距離と隣接サイトの数の2つの方法を使用しています。私の座標はすべて緯度と経度です

これは私のデータのようです:

    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                                 

隣の列に最も近い隣の池の名前、その緯度と経度をn.latとn.longに、2つの池間の距離をn.distanceに、エリア、キャノピーとavg.depthを適切な各列。

第二に、ターゲット池から1500m以内の池の数をradius1500に入れたいです。

私が望む距離/数を計算するのに役立つ関数またはパッケージを知っている人はいますか?それが問題であれば、必要な他のデータを入力するのは難しくありませんが、最も近い隣人の名前と距離、さらに1500m以内の池の数は本当に助けが必要です。

ありがとうございました。

23
user2934942

最適なオプションは、ライブラリ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)

2番目に短い距離を見つける(最も近い距離はそれ自体のポイントであるため、2番目に短い距離を使用します)

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

これは、ポイントが地球全体に散らばっていて、座標が度数である場合、より良い結果を提供するはずです

35
Zbynek

@Zbynekによって提案されたソリューションは非常に素晴らしいですが、もしあなたが私のような2 kmの距離を探しているなら、私はこのソリューションを提案しています。

   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")

座標が長くて緯度の場合、最終的にkm単位で距離を取得します。

それを改善するための提案はありますか?

1
Nico Coallier