How to Calculate Euclidean distance from sf data frame points in R

856 Views Asked by At

How do I calculate Euclidean distance in km from a spatial point that has been converted from a geometry column into a data frame. (The points are points which were derived from a spatial join of spatial data and polygon centroids)

I tried data_sample <- data_sample %>% mutate(distance= distm(cbind(origin_y,origin_x), cbind(dest_y,dest_x),fun = distHaversine)/1000)

and the error i'm getting is Error in .pointsToMatrix(x) : longitude > 360

Below is a sample data frame
data_sample <- data.frame(
    origin_x = c(
        623613.87,
        625678.02,
        625678.02,
        624359.91,
        628136.40,
        628136.40,
        628136.40,
        628136.40,
        632329.70
    ),
    origin_y = c(
        6438093.66,
        6455468.02,
        6455468.02,
        6449819.06,
        6462017.42,
        6462017.42,
        6462017.42,
        6462017.42,
        6446947.75
    ),
    dest_x = c(
        659627.84,
        642136.20,
        642136.20,
        630395.03,
        628422.74,
        642136.20,
        642136.20,
        659627.84,
        659627.84
    ),
    dest_y = c(
        6473200.36,
        6456562.78,
        6456562.78,
        6451979.98,
        6459817.02,
        6456562.78,
        6456562.78,
        6473200.36,
        6473200.36)
)

2

There are 2 best solutions below

1
On BEST ANSWER

Is there any reason not to use the sf builtin function st_distance??

library(sf)
# Using your data, but separate data.frames
origin_df <- data.frame(
    origin_x = c(623613.87,
            625678.02,
            625678.02,
            624359.91,
            628136.40,
            628136.40,
            628136.40,
            628136.40,
            632329.70
        ),         
    origin_y = c(
            6438093.66,
            6455468.02,
            6455468.02,
            6449819.06,
            6462017.42,
            6462017.42,
            6462017.42,
            6462017.42,
            6446947.75)
    )
    
dest_df <- data.frame(
    dest_x = c(
            659627.84,
            642136.20,
            642136.20,
            630395.03,
            628422.74,
            642136.20,
            642136.20,
            659627.84,
            659627.84
        ),
    dest_y = c(
            6473200.36,
            6456562.78,
            6456562.78,
            6451979.98,
            6459817.02,
            6456562.78,
            6456562.78,
            6473200.36,
            6473200.36)
    )
# Now convert to sf objects
# Just guessing at the CRS. Replace with the correct one
origin_sf = st_as_sf(origin_df, coords=c("origin_x", "origin_y"), crs="EPSG:32632")  
dest_sf <- st_as_sf(dest_df, coords=c("dest_x", "dest_y"), crs="EPSG:32632")

# Now get the distance matrix, (will be in meters, since the CRS units are meters
dist_matrix <- st_distance(origin_sf, dest_sf)
# Dispaly in kilometers
(dist_matrix)
         [,1]     [,2]     [,3]      [,4]      [,5]     [,6]     [,7]     [,8]
 [1,] 50.29400 26.15693 26.15693 15.453608 22.249261 26.15693 26.15693 50.29400
 [2,] 38.30178 16.49455 16.49455  5.866567  5.142693 16.49455 16.49455 38.30178
 [3,] 38.30178 16.49455 16.49455  5.866567  5.142693 16.49455 16.49455 38.30178
 [4,] 42.31444 19.01248 19.01248  6.410324 10.791932 19.01248 19.01248 42.31444
 [5,] 33.41809 15.02490 15.02490 10.288421  2.218953 15.02490 15.02490 33.41809
 [6,] 33.41809 15.02490 15.02490 10.288421  2.218953 15.02490 15.02490 33.41809
 [7,] 33.41809 15.02490 15.02490 10.288421  2.218953 15.02490 15.02490 33.41809
 [8,] 33.41809 15.02490 15.02490 10.288421  2.218953 15.02490 15.02490 33.41809
 [9,] 37.87331 13.73376 13.73376  5.391316 13.449255 13.73376 13.73376 37.87331
          [,9]
 [1,] 50.29400
 [2,] 38.30178
 [3,] 38.30178
 [4,] 42.31444
 [5,] 33.41809
 [6,] 33.41809
 [7,] 33.41809
 [8,] 33.41809
 [9,] 37.87331

And responding to the additional comment from william-g-k:

dist_km = dist_matrix / 1000
dist_km = as.data.frame(matrix(dist_km, nrow=1))
4
On

I am not 100% sure but looks like a problem with the coordinate system. I guess the distm()function takes values in degrees for latitude and longitude. Before converting the geometry column to data frame change the coordinate system of your data. From package 'sf' use st_crs() to find the current coordinate system and change to something like WGS 84 using st_transform().