1

I have coordinates for hundreds of cities. From climate model data I want to find the closest coordinates to my cities. I can do this individually for each city using the code below, but there must be an easier way to do this for all cities rather than listing each one out like below?

# Resolution of climate model data
OBS.lat = seq(-90, 90, 0.5)
OBS.lon = seq(-180, 180, 0.5)

# Set coordinates for cities
BERLlat = 52.52
BERLlon = 13.39

BERNlat = 46.95
BERNlon = 7.45

BUElat = -34.60
BUElon = -58.38

BERL.lat=which.min(abs(OBS.lat-BERLlat))
BERL.lon=which.min(abs(OBS.lon-BERLlon))

BERN.lat=which.min(abs(OBS.lat-BERNlat))
BERN.lon=which.min(abs(OBS.lon-BERNlon))

BUE.lat=which.min(abs(OBS.lat-BUElat))
BUE.lon=which.min(abs(OBS.lon-BUElon))
DJ-AFC
  • 569
  • 6
  • 16
  • Have you used [`sf`](https://github.com/r-spatial/sf) at all? – camille Oct 02 '19 at 14:04
  • No, but thanks @camille - I will have a look. – DJ-AFC Oct 02 '19 at 16:01
  • Similar posts: https://stackoverflow.com/q/47663254/5325862, https://stackoverflow.com/q/21977720/5325862, https://stackoverflow.com/q/31668163/5325862, https://stackoverflow.com/q/45576214/5325862 – camille Oct 02 '19 at 17:02
  • Possible duplicate of [Geographic / geospatial distance between 2 lists of lat/lon points (coordinates)](https://stackoverflow.com/questions/31668163/geographic-geospatial-distance-between-2-lists-of-lat-lon-points-coordinates) – camille Oct 02 '19 at 17:07

1 Answers1

1

I agree with some of the comments that using the sf package (and other geospatial ones) would potentially make sense for this type of exercise. However, to answer your question directly with just base R and the setup you have, one step improvement is to put the which.min(abs()) call into an actual function and use lapply to do the iteration for you, which also requires that the city coordinates and names are put into vectors and/or data frames.

# Resolution of climate model data
OBS.lat = seq(-90, 90, 0.5)
OBS.lon = seq(-180, 180, 0.5

# set the city names and coordinates into vectors instead
city_names <- c("BERL","BERN","BUE")
city_lat <- c(52.52, 46.95, -34.60)
city_long <- c(13.39, 7.45, -58.38)

# define a local function to find coordinates
find_dist <- function(x, obs) {
  return(which.min(abs(obs-x)))
}    

# do the iteration with the lapply function and unlist the results
lats <- unlist(lapply(city_lat,find_dist,OBS.lat))
lons <- unlist(lapply(city_long,find_dist,OBS.lon))

# put into a data frame for viewing
data.frame(city_names, lats, lons)

The results are the same as your code but in a dataframe format.

## Output - same results as in your code
#   city_names lats lons
# 1       BERL  286  388
# 2       BERN  275  376
# 3        BUE  112  244
Rob
  • 265
  • 2
  • 11