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")
В итоге вы получите расстояние в км, если ваши координаты длинны и лат.
Любые предложения, чтобы сделать его лучше?