Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Geosphere/dplyr: create matrix of distance between coordinates

I want to create a "matrix" of the distance between multiple coordinates with each other. Preferably using dplyr/geosphere. I already saw that the geosphere package offers this. I managed to create the distance between two vectors but I have difficulties creating the full matrix.

This is the sample table with multiple coordinates.

df <- data.frame(latitude = c(49.48609,-8.14671,11.28625),
                 longitude = c(8.463678,143.05793,-11.18285))

  latitude  longitude
1 49.48609   8.463678
2 -8.14671 143.057930
3 11.28625 -11.182850

And this is the output I am looking for:

  latitude    longitude    distance-latlon1    distance-latlon2   distance-latlon3                 
1 49.48609     8.463678    NA                  *latlon2><latlon1  *latlon3><latlon1
2 -8.14671   143.057930    *latlon1><latlon2   NA                 *latlon3><latlon2
3 11.28625   -11.182850    *latlon1><latlon3   *latlon2><latlon3  NA

I tried out using geosphere but I only found a way to calculate the distance between two columns (which in this snippet results in a 0).

library(geosphere) 
df$distance <- distVincentyEllipsoid(df[,c('longitude','latitude')],
                                     df[,c('longitude','latitude')])
like image 437
Joshua Zecha Avatar asked Aug 20 '17 15:08

Joshua Zecha


2 Answers

You need the distm function of the geosphere-package. With:

# create a distance matrix
m <- distm(df[2:1], df[2:1], fun = distVincentyEllipsoid)

# replace the diagonal with NA
diag(m) <- NA

# make column names for the distance matrix
colnames(m) <- paste0('r',1:nrow(df))

# bind the distance matrix to the dataframe
cbind.data.frame(df, m)

you get:

  latitude  longitude       r1       r2       r3
1 49.48609   8.463678       NA 13792423  4606658
2 -8.14671 143.057930 13792423       NA 17189185
3 11.28625 -11.182850  4606658 17189185       NA
like image 134
Jaap Avatar answered Sep 23 '22 16:09

Jaap


Instead of distVincentyEllipsoid I would use the faster and more precise distGeo

df = df[,2:1] # the order should be longitude, latitude!
distm(df, df, distGeo)

or

library(raster)
d <- pointDistance(df)

perhaps followed by

as.matrix(as.dist(d))
like image 39
Robert Hijmans Avatar answered Sep 24 '22 16:09

Robert Hijmans