J'essaie de comprendre à quel point certains points sont isolés dans mon ensemble de données. J'utilise deux méthodes pour déterminer l'isolement, la distance du plus proche voisin et le nombre de sites voisins dans un rayon donné. Toutes mes coordonnées sont en latitude et longitude
Voici à quoi ressemblent mes données:
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
Je veux mettre le nom de l'étang voisin le plus proche dans la colonne voisine, son lat et long en n.lat et n.long, la distance entre les deux étangs en n.distance, et la zone, la canopée et la profondeur moyenne en chacune des colonnes appropriées.
Deuxièmement, je veux mettre le nombre d'étangs à moins de 1500m de l'étang cible dans radius1500.
Quelqu'un connaît-il une fonction ou un package qui m'aidera à calculer les distances/nombres que je veux? Si c'est un problème, il ne sera pas difficile d'entrer les autres données dont j'ai besoin, mais le nom et la distance du voisin le plus proche, ainsi que le nombre d'étangs à moins de 1500 mètres, sont ce pour quoi j'ai vraiment besoin d'aide.
Je vous remercie.
La meilleure option consiste à utiliser les bibliothèques sp
et rgeos
, qui vous permettent de construire des classes spatiales et d'effectuer un géotraitement.
library(sp)
library(rgeos)
Lisez les données et transformez-les en objets spatiaux:
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"
Maintenant, calculez les distances par paires entre les points
d <- gDistance(sp.mydata, byid=T)
Trouver la deuxième distance la plus courte (la distance la plus proche est du point par rapport à lui-même, utilisez donc la deuxième plus courte)
min.d <- apply(d, 1, function(x) order(x, decreasing=F)[2])
Construire un nouveau bloc de données avec les variables souhaitées
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
Edit: si les coordonnées sont en degrés et que vous souhaitez calculer la distance en kilomètres, utilisez le package geosphere
library(geosphere)
d <- distm(sp.mydata)
# rest is the same
Cela devrait fournir de meilleurs résultats, si les points sont dispersés à travers le globe et les coordonnées sont en degrés
La solution proposée par @Zbynek est plutôt sympa mais si vous cherchez une distance entre deux voisins en km comme je le suis, je vous propose cette solution.
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")
Vous finissez par obtenir une distance en km si vos coordonnées sont longues et latentes.
Des suggestions pour l'améliorer?