1
votes

I have a problem that is very similar to this SO post:

Geographic / geospatial distance between 2 lists of lat/lon points (coordinates)

Here is an edited example set of coordinates that illustrates my case:

require(tidyverse)

list1 <- data.frame(longitude = c(72, 74, 76, 78, 79, 82), 
                    latitude = c(20.5, 19, 19.5, 20, 22, 21),
                    area = "A")
list2 <- data.frame(longitude = c(71, 73, 75, 77, 79, 78.5, 72), 
                    latitude = c(21.5, 22, 20.5, 23, 23.5, 24, 24), 
                    area = "B")

df <- bind_rows(list1, list2)

ggplot(data = df) +
    geom_point(aes(x = longitude, y = latitude, color = area)) +
    geom_line(data = list1, aes(x = longitude, y = latitude, color = area)) +
    geom_line(data = list1[c(2,6),], aes(x = longitude, y = latitude, color = area)) +
    geom_line(data = list1[c(1,4),], aes(x = longitude, y = latitude, color = area)) +
    geom_line(data = list2[c(1,7),], aes(x = longitude, y = latitude, color = area)) +
    geom_line(data = list2[c(7,6),], aes(x = longitude, y = latitude, color = area)) +
    geom_line(data = list2[c(6,5),], aes(x = longitude, y = latitude, color = area)) +
    geom_line(data = list2[c(5,3),], aes(x = longitude, y = latitude, color = area)) +
    geom_line(data = list2[c(3,1),], aes(x = longitude, y = latitude, color = area))

ggplot2 output

So I need to calculate smallest distances between two lists of coordinate points. I have been able to make this work, but I have noticed that I need something more efficient - the data is just too large.

One possibility that I have entertained, is to form non-overlapping polygons of these areas and calculate the distance from one set of points to the neighboring polygon. Is there a way to form these polygons? Convex hulls is not an options since the areas are pretty ragged.

Another option could be to form a line that runs between the areas.

Edit: I added some lines in the figure in order to illustrate the polygons.

2
Can you share a sample of your data with us? It'd be easier to help you outpatL
I'm not too familiar with geospatial topics, but maybe you can adapt this answer to calculate min distance, and maybe use a different distance if desired.Alexis
patL: I now included a small example with some bogus data.Antti
"is to form non-overlapping polygons of these areas and calculate the distance from one set of points to the neighboring polygon." - could you draw the polygons you are talking about for your test data? (using a paint program maybe?)Spacedman

2 Answers

1
votes

Perhaps this is what you are looking for?

#load libraries
library(dplyr)
library(sf)

#create row_id's, and make it a simple (spatial) feature
list1.sf <- list1 %>% 
  mutate( id = row_number() ) %>% 
  st_as_sf( coords = c("longitude", "latitude"), crs = 4326 )
list2.sf <- list2 %>% 
  mutate( id = row_number() ) %>% 
  st_as_sf( coords = c("longitude", "latitude"), crs = 4326 )

#find nearest points in list2 for each id in list1, and as a bonus, calculate the distance to this point
list1.sf %>% 
  dplyr::group_by( id ) %>%
  dplyr::mutate( np = sf::st_nearest_feature( geometry, list2.sf ),
                 dist_np = as.numeric( sf::st_distance( geometry, list2.sf[np,] ) ) )


# Simple feature collection with 6 features and 4 fields
# geometry type:  POINT
# dimension:      XY
# bbox:           xmin: 72 ymin: 19 xmax: 82 ymax: 22
# epsg (SRID):    4326
# proj4string:    +proj=longlat +datum=WGS84 +no_defs
# # A tibble: 6 x 5
# # Groups:   id [6]
# area     id    geometry    np dist_np
# * <fct> <int> <POINT [°]> <int>   <dbl>
# 1 A         1   (72 20.5)     1 151880.
# 2 A         2     (74 19)     3 196361.
# 3 A         3   (76 19.5)     3 152335.
# 4 A         4     (78 20)     3 318287.
# 5 A         5     (79 22)     5 166111.
# 6 A         6     (82 21)     5 415019.
0
votes

You can calculate the euclidean distance I change a bit the data set. I drop last column.

x1 <- data.frame(longitude = c(72, 74, 76, 78, 79, 82), 
                    latitude = c(20.5, 19, 19.5, 20, 22, 21))
x2 <- data.frame(longitude = c(71, 73, 75, 77, 79, 78.5, 72), 
                    latitude = c(21.5, 22, 20.5, 23, 23.5, 24, 24))

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


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