Skip to content

Commit

Permalink
Add arc_geo_categories
Browse files Browse the repository at this point in the history
  • Loading branch information
dieghernan committed Jan 11, 2024
1 parent 199b827 commit b982e3a
Show file tree
Hide file tree
Showing 19 changed files with 761 additions and 11 deletions.
1 change: 1 addition & 0 deletions .Rbuildignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@
^\.github$
^data-raw$
^vignettes/featuretypes\.Rmd\.orig$
^docs$
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ CRAN-SUBMISSION
cran-comments.md
.github/pkg.lock
inst/doc
docs
3 changes: 0 additions & 3 deletions CITATION.cff
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,6 @@ references:
email: jeroen@berkeley.edu
orcid: https://orcid.org/0000-0002-4035-0289
year: '2024'
identifiers:
- type: url
value: https://arxiv.org/abs/1403.2805
version: '>= 1.7.0'
- type: software
title: knitr
Expand Down
1 change: 1 addition & 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(arc_geo)
export(arc_geo_categories)
export(arc_geo_multi)
export(arc_reverse_geo)
export(arcgeocoder_check_access)
Expand Down
3 changes: 2 additions & 1 deletion R/arc_geo.R
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@
#' You can specify multiple country codes to limit results to more than one
#' country.
#' @param category A place or address type that can be used to filter results.
#' See [arc_categories] for details.
#' Several values can be used as well as a comma-separated string (i.e.
#' `"Cinema,Museum`). See [arc_categories] for details.
#'
#' @inheritParams arc_reverse_geo
#'
Expand Down
259 changes: 259 additions & 0 deletions R/arc_geo_categories.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,259 @@
#' Geocode places on a given area by category
#'
#' @description
#' This function is useful for extracting places with a given category (or list
#' of categories) near or within a given location or area. This is a wrapper
#' of [arc_geo()].
#'
#' See [arc_categories] for a detailed explanation and available values.
#'
#' **Note that** for obtaining results it is needed:
#' - Either to provide a pair of coordinates (`x,y` parameters) that would be
#' used as a reference for geocoding,
#' - Or a viewbox (aka bounding box) on the `bbox` parameter defining an
#' desired extent of the results.
#'
#' It is possible to combine the two approaches (i.e. providing `x,y,bbox`
#' values) in order to boost the geocoding process. See **Examples**.
#'
#' @inheritParams arc_geo
#' @inheritParams arc_reverse_geo
#' @inheritDotParams arc_geo -address
#' @param bbox A numeric vector of latitude and longitude
#' `c(minX, minY, maxX, maxY)` that restrict the search area.
#' See **Details**.
#' @param name Optionally, a string indicating the name or address of the
#' desired results.
#'
#' @details
#'
#' Bounding boxes can be located using different online tools, as
#' [Bounding Box Tool](https://boundingbox.klokantech.com/).
#'
#' For a full list of valid amenities see [arc_categories].
#'
#' @seealso
#' [ArcGIS REST Category
#' filtering](https://developers.arcgis.com/rest/geocode/api-reference/geocoding-category-filtering.htm)

Check warning on line 37 in R/arc_geo_categories.R

View workflow job for this annotation

GitHub Actions / Run lintr scanning

file=R/arc_geo_categories.R,line=37,col=81,[line_length_linter] Lines should not be more than 80 characters. This line is 104 characters.
#'
#' @family geocoding
#'
#' @return A \CRANpkg{tibble} with the results. See the details of the output
#' in [ArcGIS REST API Service
#' output](https://developers.arcgis.com/rest/geocode/api-reference/geocoding-service-output.htm)

Check warning on line 43 in R/arc_geo_categories.R

View workflow job for this annotation

GitHub Actions / Run lintr scanning

file=R/arc_geo_categories.R,line=43,col=81,[line_length_linter] Lines should not be more than 80 characters. This line is 97 characters.
#'
#' @export
#' @examplesIf arcgeocoder_check_access()
#' \donttest{
#' # Full workflow: Gas Stations near Carabanchel, Madrid
#'
#' # Get Carabanchel
#' carab <- arc_geo("Carabanchel, Madrid, Spain")
#'
#' # Ex1: Search near Carabanchel (not restricted)
#' ex1 <- arc_geo_categories("Gas Station",
#' # Location
#' x = carab$lon, y = carab$lat,
#' limit = 50, full_results = TRUE
#' )
#'
#' plot(carab$lon, carab$lat,
#' col = "red", pch = 19, cex = 3,
#' xlim = c(-3.8, -3.65), ylim = c(40.3, 40.5),
#' xlab = "long", ylab = "lat", main = "Example 1: Search near"
#' )
#'
#' # BBox of Carabanchel
#' rect(carab$xmin, carab$ymin, carab$xmax, carab$ymax,
#' border = "blue",
#' col = NULL
#' )
#' # Points may be far away
#' points(ex1$lon, ex1$lat)
#'
#'
#' # Example 2: Include part of the name, different results
#'
#' ex2 <- arc_geo_categories("Gas Station",
#' # Name
#' name = "Repsol",
#' # Location
#' x = carab$lon, y = carab$lat,
#' limit = 50, full_results = TRUE
#' )
#'
#'
#' plot(carab$lon, carab$lat,
#' col = "red", pch = 19, cex = 3,
#' xlim = c(-3.8, -3.65), ylim = c(40.3, 40.5),
#' xlab = "long", ylab = "lat", main = "Example 2: Search near with name"
#' )
#' # BBox of Carabanchel
#' rect(carab$xmin, carab$ymin, carab$xmax, carab$ymax,
#' border = "blue",
#' col = NULL
#' )
#' # Points may be far away
#' points(ex2$lon, ex2$lat)
#'
#' # Example 3: Near within a extent
#'
#' ex3 <- arc_geo_categories("Gas Station",
#' name = "Repsol",
#' bbox = c(carab$xmin, carab$ymin, carab$xmax, carab$ymax),
#' limit = 50, full_results = TRUE
#' )
#'
#'
#' plot(carab$lon, carab$lat,
#' col = "red", pch = 19, cex = 3,
#' xlim = c(-3.8, -3.65), ylim = c(40.3, 40.5),
#' xlab = "long", ylab = "lat",
#' main = "Example 3: Search near with name and bbox"
#' )
#' # BBox of Carabanchel
#' rect(carab$xmin, carab$ymin, carab$xmax, carab$ymax,
#' border = "blue",
#' col = NULL
#' )
#' # Points may be far away
#' points(ex3$lon, ex3$lat)
#' }
arc_geo_categories <- function(category, x = NULL, y = NULL, bbox = NULL,
name = NULL, lat = "lat", long = "lon",
limit = 1, full_results = FALSE,
return_addresses = TRUE, verbose = FALSE,
progressbar = TRUE, custom_query = list(), ...) {
# Prepare location
locs <- validate_location(x, y)

# Prepare bbox
bbox <- validate_bbox(bbox)

if (all(is.na(c(locs, bbox)))) {
stop("Provide either a valid combination of x,y parameters or a valid bbox")
}

# Ready for preparing query
base_tbl <- dplyr::tibble(
q_category = category,
q_x = locs[1],
q_y = locs[2],
q_bbox_xmin = bbox[1],
q_bbox_ymin = bbox[2],
q_bbox_xmax = bbox[3],
q_bbox_ymax = bbox[4]
)


if (!any(is.na(locs))) {
custom_query$location <- paste0(locs, collapse = ",")
}

if (!any(is.na(bbox))) {
custom_query$searchExtent <- paste0(bbox, collapse = ",")
}

if (is.null(name)) name <- ""
api_res <- arc_geo(
category = category, address = name,
lat = lat, long = long, limit = limit,
full_results = full_results,
return_addresses = return_addresses,
verbose = verbose, progressbar = progressbar,
custom_query = custom_query, ...
)

end <- dplyr::bind_cols(base_tbl, api_res)

# Remove fields
end <- end[, setdiff(names(end), "query")]

return(end)
}


validate_location <- function(x = NULL, y = NULL) {
if (is.null(x)) x <- NA
if (is.null(y)) y <- NA
# If both NAs then return NAs
if (all(is.na(x), is.na(y))) {
return(c(NA, NA))
}

# If any NA return NAs with message
if (any(is.na(x), is.na(y))) {
message("Either x or y are missing. `location` parameter won't be used")
return(c(NA, NA))
}

# Check inputs
if (!is.numeric(x) || !is.numeric(y)) {
stop("x and y must be numeric")
}

# Not vectorized
x <- x[1]
y <- y[1]


# Lat
y_cap <- pmax(pmin(y, 90), -90)

if (!identical(y_cap, y)) {
message("\nlatitudes have been restricted to [-90, 90]")
}

# Lon
x_cap <- pmax(pmin(x, 180), -180)

if (!all(x_cap == x)) {
message("\nlongitudes have been restricted to [-180, 180]")
}

return(c(x_cap, y_cap))
}

validate_bbox <- function(bbox = NULL) {
if (is.null(bbox)) {
return(c(NA, NA, NA, NA))
}

# If any NA return NAs with message
if (any(is.na(bbox))) {
message("`bbox` with NA values. `bbox` parameter won't be used")
return(c(NA, NA, NA, NA))
}

if (length(bbox) < 4) {
message("`bbox` with less than 4 values. `bbox` parameter won't be used")
return(c(NA, NA, NA, NA))
}

if (!is.numeric(bbox)) {
message("`bbox` not numeric. `bbox` parameter won't be used")
return(c(NA, NA, NA, NA))
}

# Start here to assess
bbox <- bbox[1:4]

# Lon
xs <- bbox[c(1, 3)]
xs_cap <- pmax(pmin(xs, 180), -180)

if (!all(xs_cap == xs)) {
message("\nbbox xmin,xmax have been restricted to [-180, 180]")
}


# Lat
ys <- bbox[c(2, 4)]
ys_cap <- pmax(pmin(ys, 90), -90)

if (!all(ys_cap == ys)) {
message("\nbbox ymin,ymax have been restricted to [-90, 90]")
}

return(c(xs_cap[1], ys_cap[1], xs_cap[2], ys_cap[2]))
}
2 changes: 1 addition & 1 deletion R/data.R
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@
#'
#' sea_2 <- arc_geo("sea",
#' custom_query = list(outFields = "LongLabel,Type"),
#' limit = 2, category = "Restaurant"
#' limit = 2, category = "Food"
#' )
#'
#' dplyr::glimpse(sea_2)
Expand Down
4 changes: 2 additions & 2 deletions codemeta.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"name": "R",
"url": "https://r-project.org"
},
"runtimePlatform": "R version 4.3.2 (2023-10-31)",
"runtimePlatform": "R version 4.3.2 (2023-10-31 ucrt)",
"author": [
{
"@type": "Person",
Expand Down Expand Up @@ -130,7 +130,7 @@
},
"applicationCategory": "cartography",
"keywords": ["r", "geocoding", "arcgis", "address", "reverse-geocoding", "rstats", "r-package", "api-wrapper", "api-rest", "arcgis-api", "gis"],
"fileSize": "175.497KB",
"fileSize": "6204.698KB",
"citation": [
{
"@type": "SoftwareSourceCode",
Expand Down
Binary file modified data/arc_categories.rda
Binary file not shown.
2 changes: 2 additions & 0 deletions inst/WORDLIST
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ Addr
ArcGIS
CMD
CodeFactor
Geocode
Geocodes
Geocoding
InlandPsych
Expand All @@ -21,3 +22,4 @@ geocoding
lon
multifield
tibble
viewbox
2 changes: 1 addition & 1 deletion inst/schemaorg.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"name": "R",
"url": "https://r-project.org"
},
"runtimePlatform": "R version 4.3.2 (2023-10-31)",
"runtimePlatform": "R version 4.3.2 (2023-10-31 ucrt)",
"version": "0.0.0.9000"
},
{
Expand Down
2 changes: 1 addition & 1 deletion man/arc_categories.Rd

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

4 changes: 3 additions & 1 deletion man/arc_geo.Rd

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

Loading

0 comments on commit b982e3a

Please sign in to comment.