web-dev-qa-db-fra.com

Comment calculer la distance euclidienne entre deux points définis par une matrice contenant x, y?

Je suis très perdu dans calcul de la distance euclidienne . J'ai trouvé des fonctions dist2 {SpatialTools} ou rdist {fields} pour le faire, mais elles ne fonctionnent pas comme prévu.

Je suppose qu'un point a deux coordonnées dans le système carthésien, donc [x, y]. Pour mesurer la distance entre 2 points (définis par rangée), il me faut 4 coordonnées pour 2 points, donc le point A: [x1, y1] le point B: [x2, y2]

Points coordinations:

Points position

A[0,1]
B[0,0] 
C[1,1]
D[1,1]

J'ai deux matrices: x1 (A et C sont là, définies par des lignes) et x2 (contient B et D). Ecrit dans la matrice:

library("SpatialTools")
x1<-matrix(c(0,1,1,1), nrow = 2, ncol=2, byrow=TRUE)
x2<-matrix(c(0,0,1,1), nrow = 2, ncol=2, byrow=TRUE)

alors j'obtiens

> x1
     [,1] [,2]
[1,]    0    1    #(as xy coordinates of A point)
[2,]    1    1    #(same for C point)

> x2
     [,1] [,2]
[1,]    0    0    #(same for B point)
[2,]    1    1    #(same for D point)

Pour calculer la distance euclidienne entre

A <-> B  # same as x1[1,] <-> x2[1,]
C <-> D  # same as x1[2,] <-> x2[2,]

Je suppose que pour obtenir EuclidDist :

> x1                           x2                         EuclidDist
     [,1] [,2]                      [,1] [,2]
[1,]    0    1    #A         [1,]    0    0    #B             1
[2,]    1    1    #B         [2,]    1    1    #D             0

Je voudrais juste obtenir le vecteur des distances entre deux points identifiés par les coordonnées [x, y] , cependant, en utilisant dist2, je me procure une matrice:

> dist2(x1,x2)
         [,1] [,2]
[1,] 1.000000    1
[2,] 1.414214    0

Ma question est la suivante: quels chiffres décrivent la distance euclidienne réelle entre A-B et C-D à partir de cette matrice? Est-ce que je comprends mal quelque chose? Merci beaucoup pour chaque conseil ou toute explication.

6
maycca

Si vous voulez juste un vecteur, quelque chose comme cela fonctionnera pour vous.

Essayez quelque chose comme ça:

euc.dist <- function(x1, x2) sqrt(sum((x1 - x2) ^ 2))

library(foreach)
foreach(i = 1:nrow(x1), .combine = c ) %do% euc.dist(x1[i,],x2[i,])

Cela fonctionnera pour toutes les dimensions.

Si vous ne voulez pas utiliser foreach, vous pouvez utiliser une simple boucle:

dist <- NULL
for(i in 1:nrow(x1)) dist[i] <- euc.dist(x1[i,],x2[i,])
dist

Bien que, je recommanderais foreach (car il est très facile de réaliser de telles tâches). En savoir plus à ce sujet dans la documentation du paquet.

12
Shambho
library(rgdal)

library(sp)

##**COORDINATES** DATAFRAME THAT CONTENT THE LATITUDE (LAT) AND LONGITUDE 
##(LON) IN THE COORDINATE REFERENT SYSTEM (CRS) WGS84.

coordinates(COORDINATES) <- ~ LON + LAT

proj4string(COORDINATES) <- CRS("+proj=longlat +datum=WGS84") #ASSIGN THE CRS

Zone <- input$Zone   #UTM ZONE FOR YOUR COUNTRY

COORDINATES <- spTransform(COORDINATES, CRS(paste("+proj=utm", " +zone=", 
                           Zone, " +ellps=WGS84", " +datum=WGS84", " 
                           +units=m", sep="")))  #REPROJECT THE CRS
COORDINATES <- as.data.frame(COORDINATES)
X <- COORDINATES$LON  #EXTRACT THE LOGITUDE VECTOR
Y <- COORDINATES$LAT  #EXTRACT THE LATITUDE VECTOR
MX1 <- X %*% t(X) #CREATE A MATRIX FOR LONGITUDE VECTOR
MX2 <- matrix(rep(t(X),nrow(COORDINATES)), ncol = nrow(COORDINATES), 
              nrow = nrow(COORDINATES)) #CREATE A MATRIX FOR REPEAT LONGITUDE VECTOR
MX <- MX1/MX2 #DEFENITIVE MATRIX FOR LONGITUDE VECTORS
MX <- abs((MX-MX2)**2) #SQUARE SUM OF LONGITUDE VECTORS
colnames(MX)<- paste(COORDINATES$STATION) #ASSIGN COLNAMES
rownames(MX)<- paste(COORDINATES$STATION) #ASSIGN ROWNAMES
MY1 <- Y %*% t(Y) #CREATE A MATRIX FOR LATITUDE VECTOR
MY2 <- matrix(rep(t(Y), nrow(COORDINATES)), ncol = nrow(COORDINATES), 
              nrow = nrow(COORDINATES)) #CREATE A MATRIX FOR REPEAT LATITUDE VECTOR
MY <- MY1/MY2 #DEFENITIVE MATRIX FOR LATITUDE VECTORS
MY <- abs((MY-MY2)*2) #SQUARE SUM OF LONGITUDE VECTORS
colnames(MY)<- paste(COORDINATES$STATION) #ASSIGN COLNAMES
rownames(MY)<- paste(COORDINATES$STATION) #ASSIGN ROWNAMES
EUCLIDEAND <- round((sqrt(MX+MY)/1000), digits = 0) #EUCLIDEAN DISTANCE FOR THESE COORDINATES
EUCLIDEAND <- as.data.frame(EUCLIDEAND)
0
VALIZCANOS

La diagonale est ce que vous cherchez. La matrice de sortie de dist2 indique la distance entre tous les points. Le numéro de ligne de la sortie correspond à la ligne de la première entrée et la colonne de la sortie correspond à la ligne de la deuxième entrée. Voici un diagramme, j'espère que cela a du sens (c'est le genre de chose pour laquelle je souhaite que MathJax prenne en charge Stack Overflow):

dist2( A_x A_y     C_x C_y      ( AC  AD
       B_x B_y  ,  D_x D_y )  =   BC  BD ) 

dist2(   x1     ,     x2   )  =   result

Dans votre cas, vous voulez que la distance entre le premier point de x1 et le premier point de x2, puis le deuxième point de x1 et le deuxième point de x2, d'où la diagonale.

Si vous avez beaucoup de données et que vous ne vous souciez que des paires correspondantes, vous ferez bien mieux de le calculer directement:

> x1 <- matrix(c(0, 1, 1, 1), ncol = 2, byrow = T)
> x2 <- matrix(c(0, 0, 1, 1), ncol = 2, byrow = T)
> sqrt(rowSums((x1 - x2)^2))
[1] 1 0

Si vous avez un tout un lot de données (en millions de points), il vaut peut-être la peine d'utiliser foreach, comme le suggère @Shambho.

0
Gregor