Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check if location is within a certain distance of a set of other locations using R

I've been trying to solve this problem for a while now, but I can't seem to wrap my head around it. I am still new to R and a first time poster here. I tried to follow the rules as much as possible, but please let me know if I missed something or could do things better.

What I am trying to do is to match a set of places (POI's) with a set of stop locations of journeys. The locations of both sets are in latitudinal/longitudinal coordinates. If a journey location is within the radius of a POI (POI$rad), the name of the POI should be returned (POI$station).

I got this so far:

station <- c("a", "b", "c")
lat <- c(47.61870, 47.61422, 47.60603)
lng <- c(-122.34414, -122.32062, -122.32410)
rad <- c(0.075, 0.075, 0.175)
POI <- as.data.frame(list(station=station, lat=lat, lng=lng, rad=rad), 
       row.names = NULL, stringsAsFactors = FALSE)

journeynr <- c(1:6)
lat <- c(47.60643, 47.61013, 47.61855, 47.61855, 47.61432,47.61408)
lng <- c(-122.32404, -122.33355, -122.33263, -122.34437, -122.32082, -122.31914)
journey <- as.data.frame(list(journeynr=journeynr, lat=lat, lng=lng), 
           row.names = NULL, stringsAsFactors = FALSE)

earth.dist <- function (long1, lat1, long2, lat2)
{
  rad <- pi/180
  a1 <- lat1 * rad
  a2 <- long1 * rad
  b1 <- lat2 * rad
  b2 <- long2 * rad
  dlon <- b2 - a2
  dlat <- b1 - a1
  a <- (sin(dlat/2))^2 + cos(a1) * cos(b1) * (sin(dlon/2))^2
  c <- 2 * atan2(sqrt(a), sqrt(1 - a))
  R <- 6378.145
  d <- (R * c)
  return(d)
}

journey$test <- ifelse(earth.dist(journey$lat, journey$lng, 
                POI$lat, POI$lng) <= POI$rad, POI$station ,NA)

This doesn't really do what I want, because I think this compares row 1 of 'journey' with row 1 of 'POI', row 2 of 'journey' with row 2 of 'POI', etc. If I reduce POI to a single row by adding:

POI <- subset(POI, POI$station =="c")

Right before the last line, it does seem to work correctly. Unfortunately, only for that one POI. What I think I want is that row 1 of 'journey' gets compared with ALL rows of 'POI'.

Would this indeed be the right way to do this? If so, what am I doing wrong? If not ... what am I doing wrong?

Thanks for the help!

like image 508
roger Avatar asked Dec 06 '25 03:12

roger


1 Answers

Is it this, want you were looking for?

d <- outer(1:nrow(journey), 1:nrow(POI), 
       FUN=function(i, j) 
          earth.dist(journey[i,"lng"], journey[i,"lat"], 
                POI[j,"lng"], POI[j, "lat"]))

apply(apply(d, 1, "-", POI$rad) < 0, 2, function(x) POI$station[x])
like image 58
Andri Signorell Avatar answered Dec 08 '25 17:12

Andri Signorell



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!