Skip to content

Commit

Permalink
⭐ Add new find_nearest_coord as a new function
Browse files Browse the repository at this point in the history
  • Loading branch information
truenomad committed May 20, 2024
1 parent ed18bf8 commit 9578e16
Show file tree
Hide file tree
Showing 7 changed files with 123 additions and 4 deletions.
2 changes: 2 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Generated by roxygen2: do not edit by hand

export(detect_date_format)
export(find_nearest_coord)
export(get_multi_ona_data)
export(get_ona_data)
export(get_updated_ona_data)
Expand All @@ -13,6 +14,7 @@ import(doFuture)
import(dplyr)
import(foreach)
import(future)
import(sf)
importFrom(cli,cli_alert_warning)
importFrom(cli,cli_h2)
importFrom(cli,cli_text)
Expand Down
58 changes: 58 additions & 0 deletions R/find_nearest_coord.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#' Find Nearest Coordinate from shapefile Dataset
#'
#' This function takes a pair of coordinates (longitude and latitude) and finds
#' the nearest coordinate from the `shp_global` dataset.
#'
#' The shapefile dataset should contain longitude and latitude information
#' with columns named `CENTER_LON` and `CENTER_LAT`. The function calculates the
#' distance between the target point and all points in the dataset, returning
#' the nearest coordinate.
#'
#' @param lon Numeric. Longitude of the target point.
#' @param lat Numeric. Latitude of the target point.
#' @param shapefile An optional `sf` object containing the shapefile data.
#' Defaults to `poliprep::shp_global`.
#' @param level_to_return The admin level to return.
#' @return A vector of admin level names containing the nearest coordinate from
#' the provided shapefile.
#' @examples
#' # Example usage
#' # Assuming `poliprep::shp_global` is already loaded in the environment
#' nearest_coord <- find_nearest_coord(15.28172, -4.271301)
#' print(nearest_coord)
#' @export
# Define the function
find_nearest_coord <- function(lon, lat,
shapefile = NULL,
level_to_return = "adm2") {

# Use default shapefile if none provided
if (is.null(shapefile)) {
shapefile <- poliprep::shp_global
}

# Prepare the `shp_global` dataset
res <- shapefile |>
dplyr::filter(ENDDATE > as.Date("9900-12-31")) |>
dplyr::rename(adm0 = ADM0_NAME,
adm1 = ADM1_NAME,
adm2 = ADM2_NAME) |>
dplyr::mutate(
CENTER_LON = as.numeric(CENTER_LON),
CENTER_LAT = as.numeric(CENTER_LAT)
) |>
sf::st_as_sf(coords = c("CENTER_LON", "CENTER_LAT"), crs = 4326)

# Define the target point
target_point <- sf::st_sfc(
sf::st_point(c(lon, lat)), crs = 4326
) |>
sf::st_sf()

# Find the nearest coordinate
distances <- sf::st_distance(target_point, res)
nearest_index <- which.min(distances)
nearest_coord <- res[nearest_index, ][[level_to_return]]

return(as.vector(nearest_coord))
}
3 changes: 2 additions & 1 deletion R/globals.R
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ globalVariables(
"distance", "longname_corrected", "longname_corrected2",
"match_rank", "matched_names", "form_id_num", "last_date_in_chunk", "x",
"date_last_updated", "form_id", "name_of_creator", "created_time",
"user_name", "ADM0_NAME", "ADM1_NAME", "ADM2_NAME", "ENDDATE"
"user_name", "ADM0_NAME", "ADM1_NAME", "ADM2_NAME", "ENDDATE",
"CENTER_LAT", "CENTER_LON"
)
)

6 changes: 3 additions & 3 deletions R/prep_geonames.R
Original file line number Diff line number Diff line change
Expand Up @@ -616,9 +616,9 @@ construct_geo_names <- function(data, level0, level1, level2) {
#' \code{"soundex"}.
#' @param stratify Logical; if TRUE, performs cleaning stratified by
#' admin levels to maintain hierarchical consistency.
#' @param user_name name of user to save onto the cache file.
#' Very important for future auditing if cache file is being used
#' by many. Make sure it's recognisable.
#' @param user_name Full name of user to save onto the cache file.
#' Very important for future auditing specially if cache file is being used
#' by many.
#' @param non_interactive Whether to use the interactivity or not.
#' @details
#' The function performs the following steps:
Expand Down
36 changes: 36 additions & 0 deletions man/find_nearest_coord.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file added prepped_geoname_cache.rds
Binary file not shown.
22 changes: 22 additions & 0 deletions tests/testthat/test-find_nearest_coord.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@

# set up mocek shapefile
mock_data <- data.frame(
CENTER_LON = c(-4.222, -3.2, -24.5),
CENTER_LAT = c(15.02222, 43.2, 23.5),
ENDDATE = c("9999-12-31 01:00:00", "9999-12-31 01:00:00",
"9999-12-31 01:00:00"),
ADM0_NAME = c("Mock Area 1", "Mock Area 2", "Mock Area 3"),
ADM1_NAME = c("Mock Area 1", "Mock Area 2", "Mock Area 3"),
ADM2_NAME = c("Mock Area 1", "Mock Area 2", "Mock Area 3")
)

# Test cases
testthat::test_that("find_nearest_coord returns correct area", {
result <- find_nearest_coord(shapefile = mock_data, -24.0, 15.9)
testthat::expect_equal(result, "Mock Area 3")

result2 <- find_nearest_coord(
lon = -24.0324, lat = 15.93214, level_to_return = "adm2")
testthat::expect_equal(result2, "RIBERIA BRAVA")

})

0 comments on commit 9578e16

Please sign in to comment.