Skip to content

Commit

Permalink
Merge pull request #39 from Robinlovelace/38-use-new-max_dist-functio…
Browse files Browse the repository at this point in the history
…nality-from-latest-version-of-od-to-speed-up-si_to_od

Update si_to_od() to include max_dist in {od}, close #38
  • Loading branch information
Robinlovelace authored Aug 21, 2024
2 parents 70ab502 + fa40465 commit cb36bba
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 14 deletions.
2 changes: 2 additions & 0 deletions .Rbuildignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,5 @@
^cran-comments\.md$
^CRAN-SUBMISSION$
paper
^.*\.geojson$
^.*\.zip$
1 change: 1 addition & 0 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ Suggests:
ggplot2,
knitr,
minpack.lm,
nngeo,
rmarkdown,
tmap
VignetteBuilder:
Expand Down
41 changes: 27 additions & 14 deletions R/si_to_od.R
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
#' Prepare OD data frame
#'
#' Prepares an OD data frame that next could be used to
#' estimate movement between origins and destinations
#' estimate movement between origins and destinations
#' with a spatial interaction model.
#'
#'
#' In most origin-destination datasets the spatial entities that constitute
#' origins (typically administrative zones) also represent destinations.
#' In this 'unipartite' case `origins` and `destinations` should be passed
#' the same object, an `sf` data frame representing administrative zones.
#'
#'
#' 'Bipartite' datasets, by contrast, represent
#' "spatial interaction systems where origins cannot act as
#' destinations and vice versa" (Hasova et al. [2022](https://lenkahas.com/files/preprint.pdf)).
#'
#' destinations and vice versa" (Hasova et al. [2022](https://lenkahas.com/files/preprint.pdf)).
#'
#' a different
#' `sf` object can be passed to the `destinations` argument.
#'
#'
#' @param origins `sf` object representing origin locations/zones
#' @param destinations `sf` object representing destination locations/zones
#' @param max_dist Euclidean distance in meters (numeric).
Expand Down Expand Up @@ -45,18 +45,31 @@
#' nrow(odsf) # no intrazonal flows
#' plot(odsf)
si_to_od = function(origins, destinations, max_dist = Inf, intrazonal = TRUE) {
if(identical(origins, destinations)) {
od_df = od::points_to_od(origins)
nngeo_installed = requireNamespace("nngeo", quietly = TRUE)
if (!nngeo_installed && max_dist < Inf) {
message("The nngeo package is required for fast nearest neighbor search")
}
if (max_dist < Inf && nngeo_installed) {
if (identical(origins, destinations)) {
od_df = od::points_to_od(origins, max_dist = max_dist)
} else {
od_df = od::points_to_od(origins, destinations, max_dist = max_dist)
}
} else {
od_df = od::points_to_od(origins, destinations)
if (identical(origins, destinations)) {
od_df = od::points_to_od(origins)
} else {
od_df = od::points_to_od(origins, destinations)
}
}

od_df$distance_euclidean = geodist::geodist(
x = od_df[c("ox", "oy")],
y = od_df[c("dx", "dy")],
paired = TRUE
)
# Max dist check
if(max(od_df$distance_euclidean) > max_dist) {
if (max(od_df$distance_euclidean) > max_dist && !nngeo_installed) {
nrow_before = nrow(od_df)
od_df = od_df[od_df$distance_euclidean <= max_dist, ]
nrow_after = nrow(od_df)
Expand All @@ -68,16 +81,16 @@ si_to_od = function(origins, destinations, max_dist = Inf, intrazonal = TRUE) {
pct_kept, "% of all possible OD pairs"
)
}

# Intrazonal check
if(!intrazonal){
if (!intrazonal) {
od_df = dplyr::filter(od_df, distance_euclidean > 0)
}

od_sfc = od::odc_to_sfc(od_df[3:6])
sf::st_crs(od_sfc) = 4326 # todo: add CRS argument?
od_df = od_df[-c(3:6)]

# join origin attributes
origins_to_join = sf::st_drop_geometry(origins)
names(origins_to_join) = paste0("origin_", names(origins_to_join))
Expand Down

0 comments on commit cb36bba

Please sign in to comment.