Title: | Flexible Framework for Developing Spatial Interaction Models |
---|---|
Description: | Develop spatial interaction models (SIMs). SIMs predict the amount of interaction, for example number of trips per day, between geographic entities representing trip origins and destinations. Contains functions for creating origin-destination datasets from geographic input datasets and calculating movement between origin-destination pairs with constrained, production-constrained, and attraction-constrained models (Wilson 1979) <doi:10.1068/a030001>. |
Authors: | Robin Lovelace [aut, cre] , Jakub Nowosad [aut] |
Maintainer: | Robin Lovelace <[email protected]> |
License: | AGPL (>= 3) |
Version: | 0.2.0 |
Built: | 2024-11-24 05:42:17 UTC |
Source: | https://github.com/robinlovelace/simodels |
Example dataset from York, UK
See data-raw/zones_york.qmd for details on the data source.
head(destinations_york)
head(destinations_york)
Example dataset from Australia
Regenerate the data with scripts in the data-raw
directory.
head(od_aus)
head(od_aus)
Executes a spatial interaction model based on an OD data frame and user-specified function
si_calculate( od, fun, constraint_production, constraint_attraction, constraint_total, output_col = "interaction", ... )
si_calculate( od, fun, constraint_production, constraint_attraction, constraint_total, output_col = "interaction", ... )
od |
A data frame representing origin-destination data, e.g. as created by
|
fun |
A function that calculates the interaction (e.g. the number of trips) between each OD pair |
constraint_production |
Character representing column in |
constraint_attraction |
Character representing column in |
constraint_total |
Single number representing the total interaction. This argument, when set, ensures that the sum of the interaction calculated will equal the value given. |
output_col |
Character string containing the name of the new output
column. |
... |
Arguments passed to |
An sf data frame
od = si_to_od(si_zones, si_zones, max_dist = 4000) fun_dd = function(d = "distance_euclidean", beta = 0.3) exp(-beta * d / 1000) fun_dd(d = (1:5) * 1000) od_dd = si_calculate(od, fun = fun_dd, d = distance_euclidean) plot(od$distance_euclidean, od_dd$interaction) fun = function(O, n, d, beta) O * n * exp(-beta * d / 1000) od_output = si_calculate(od, fun = fun, beta = 0.3, O = origin_all, n = destination_all, d = distance_euclidean) head(od_output) plot(od$distance_euclidean, od_output$interaction) od_pconst = si_calculate(od, fun = fun, beta = 0.3, O = origin_all, n = destination_all, d = distance_euclidean, constraint_production = origin_all) # Origin totals in OD data should equal origin totals in zone data library(dplyr) origin_totals_zones = od_pconst |> group_by(geo_code = O) |> summarise(all_od = sum(interaction)) |> sf::st_drop_geometry() zones_joined = left_join(si_zones, origin_totals_zones) plot(zones_joined$all, zones_joined$all_od) plot(od_pconst$distance_euclidean, od_pconst$interaction) plot(od_pconst["interaction"], logz = TRUE) od_dd = si_calculate(od, fun = fun_dd, d = distance_euclidean, output_col = "res") head(od_dd$res) od_dd = si_calculate(od, fun = fun_dd, d = distance_euclidean, constraint_total = 10) sum(od_dd$interaction)
od = si_to_od(si_zones, si_zones, max_dist = 4000) fun_dd = function(d = "distance_euclidean", beta = 0.3) exp(-beta * d / 1000) fun_dd(d = (1:5) * 1000) od_dd = si_calculate(od, fun = fun_dd, d = distance_euclidean) plot(od$distance_euclidean, od_dd$interaction) fun = function(O, n, d, beta) O * n * exp(-beta * d / 1000) od_output = si_calculate(od, fun = fun, beta = 0.3, O = origin_all, n = destination_all, d = distance_euclidean) head(od_output) plot(od$distance_euclidean, od_output$interaction) od_pconst = si_calculate(od, fun = fun, beta = 0.3, O = origin_all, n = destination_all, d = distance_euclidean, constraint_production = origin_all) # Origin totals in OD data should equal origin totals in zone data library(dplyr) origin_totals_zones = od_pconst |> group_by(geo_code = O) |> summarise(all_od = sum(interaction)) |> sf::st_drop_geometry() zones_joined = left_join(si_zones, origin_totals_zones) plot(zones_joined$all, zones_joined$all_od) plot(od_pconst$distance_euclidean, od_pconst$interaction) plot(od_pconst["interaction"], logz = TRUE) od_dd = si_calculate(od, fun = fun_dd, d = distance_euclidean, output_col = "res") head(od_dd$res) od_dd = si_calculate(od, fun = fun_dd, d = distance_euclidean, constraint_total = 10) sum(od_dd$interaction)
This dataset contains origin-destination data for Leeds, including the number of trips between output areas (OAs) and workplace zones (WPZs).
head(si_oa_wpz)
head(si_oa_wpz)
This dataset contains the number of trips destined for each workplace zone (WPZ) in Leeds.
See wicid.ukdataservice.ac.uk for details on the data source
and the file data-raw/si_oa_wpz.qmd
in the package repo for details on how the example dataset was generated.
head(si_oa_wpz_d) sf:::plot.sf(si_oa_wpz_d["n_d"])
head(si_oa_wpz_d) sf:::plot.sf(si_oa_wpz_d["n_d"])
This dataset contains the number of trips originating from each output area (OA) in Leeds.
head(si_oa_wpz_o) sf:::plot.sf(si_oa_wpz_o["n_o"])
head(si_oa_wpz_o) sf:::plot.sf(si_oa_wpz_o["n_o"])
Example OD dataset from the 2011 UK Census
Regenerate the data with scripts in the data-raw
directory.
head(si_od_census)
head(si_od_census)
Predict spatial interaction based on pre-trained model
si_predict( od, model, constraint_production, constraint_attraction, constraint_total, output_col = "interaction", ... )
si_predict( od, model, constraint_production, constraint_attraction, constraint_total, output_col = "interaction", ... )
od |
A data frame representing origin-destination data, e.g. as created by
|
model |
|
constraint_production |
Character representing column in |
constraint_attraction |
Character representing column in |
constraint_total |
Single number representing the total interaction. This argument, when set, ensures that the sum of the interaction calculated will equal the value given. |
output_col |
Character string containing the name of the new output
column. |
... |
Arguments passed to |
An sf data frame
si_calculate
od = si_to_od(si_zones, si_zones, max_dist = 4000) m = lm(od$origin_all ~ od$origin_bicycle) od_updated = si_predict(od, m)
od = si_to_od(si_zones, si_zones, max_dist = 4000) m = lm(od$origin_all ~ od$origin_bicycle) od_updated = si_predict(od, m)
Example dataset from Leeds, UK
Regenerate the data with scripts in the data-raw
directory.
head(si_pubs)
head(si_pubs)
Prepares an OD data frame that next could be used to estimate movement between origins and destinations with a spatial interaction model.
si_to_od(origins, destinations, max_dist = Inf, intrazonal = TRUE)
si_to_od(origins, destinations, max_dist = Inf, intrazonal = TRUE)
origins |
|
destinations |
|
max_dist |
Euclidean distance in meters (numeric). Only OD pairs that are this distance apart or less will be returned and therefore included in the SIM. |
intrazonal |
Include intrazonal OD pairs?
Intrazonal OD pairs represent movement from one
place in a zone to another place in the same zone.
|
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).
a different
sf
object can be passed to the destinations
argument.
An sf data frame
library(sf) origins = si_centroids[c(1, 2, 99), ] destinations = origins plot(origins$geometry) odsf = si_to_od(origins, destinations, max_dist = 1200) plot(odsf) # note: result contains intrazonal flows represented by linestrings # with a length of 0, e.g.: sf::st_coordinates(odsf$geometry[1]) # With different destinations compared with origins library(sf) origins = si_centroids[c(2, 99), c(1, 6, 7)] destinations = si_centroids[1, c(1, 6, 8)] odsf = si_to_od(origins, destinations) nrow(odsf) # no intrazonal flows plot(odsf)
library(sf) origins = si_centroids[c(1, 2, 99), ] destinations = origins plot(origins$geometry) odsf = si_to_od(origins, destinations, max_dist = 1200) plot(odsf) # note: result contains intrazonal flows represented by linestrings # with a length of 0, e.g.: sf::st_coordinates(odsf$geometry[1]) # With different destinations compared with origins library(sf) origins = si_centroids[c(2, 99), c(1, 6, 7)] destinations = si_centroids[1, c(1, 6, 8)] odsf = si_to_od(origins, destinations) nrow(odsf) # no intrazonal flows plot(odsf)
si_zones
and si_centroids
represent administrative zones between which
flows are to be estimated.
The schema data can be (re-)generated using code in data-raw
si_zones sf:::plot.sfg(si_zones$geometry) sf:::plot.sfg(si_centroids$geometry, add = TRUE)
si_zones sf:::plot.sfg(si_zones$geometry) sf:::plot.sfg(si_centroids$geometry, add = TRUE)
Example dataset from Australia
Regenerate the data with scripts in the data-raw
directory.
head(zones_aus)
head(zones_aus)
See data-raw/zones_york.qmd for details on the data source.
head(zones_york) sf:::plot.sfg(zones_york$geometry)
head(zones_york) sf:::plot.sfg(zones_york$geometry)