1

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.

Antti
  • 1,263
  • 2
  • 16
  • 28
  • 2
    Can you share a [sample of your data](https://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example) with us? It'd be easier to help you out – patL Aug 20 '19 at 10:09
  • 1
    I'm not too familiar with geospatial topics, but maybe you can adapt [this answer](https://stackoverflow.com/a/55666677/5793905) to calculate min distance, and maybe use a different distance if desired. – Alexis Aug 20 '19 at 10:26
  • patL: I now included a small example with some bogus data. – Antti Aug 20 '19 at 12:14
  • 1
    "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 Aug 20 '19 at 13:27

2 Answers2

3

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.
Wimpel
  • 26,031
  • 1
  • 20
  • 37
  • I think this is another version to calculate distances between two sets of points. What I'm after here is that I could turn a set to a polygon that does not overlap with the other set and then calculate distances to that polygon. Alternatively I could construct a line between these two sets and then calculate distances to that line. – Antti Aug 20 '19 at 13:14
0

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

AnnaIC
  • 49
  • 4
  • I don't think that is what I'm after. I want to calculate a distance from each point to a polygon or line that is constructed from the points that belong to the other set. – Antti Aug 20 '19 at 13:15