accessibility is an R package that offers a set of fast and convenient functions to calculate multiple transport accessibility measures. Given a pre-computed travel cost matrix in long format combined with land-use data (e.g. location of jobs, healthcare, population), the package allows one to calculate active and passive accessibility levels using multiple accessibility metrics such as: cumulative opportunity measure (using either travel time cutoff or interval), minimum travel cost to closest N number of activities, gravitational measures and different floating catchment area methods.
This vignette gives a brief introduction to the
accessibility
package with a reproducible example.
You can install accessibility
from CRAN, or use the
development version from github.
# CRAN
install.packages('accessibility')
# github
::install_github("ipeaGIT/accessibility", subdir = "r-package") devtools
The accessibility
package currently includes:
time_to_closest()
Minimum travel cost to closest
N number of opportunitiescumulative_time_cutoff()
. Traditional time
threshold-based cumulative opportunity metriccumulative_time_interval()
. A novel time interval-based
cumulative opportunity metric (forthcoming paper)gravity_access()
Gravity-based accessibilityfloating_catchment_area()
Floating catchment area
accessibility using 2SFCA
floating_catchment_area()
Floating catchment area
accessibility using BFCA
The gravity_access()
and
floating_catchment_area()
functions can use any custom
decay function that converts travel cost t_ij
to and
impedance factor. For convenience, the package currently includes the
following decay functions:
decay_binary()
Binary (aka step) decay functiondecay_exponential()
Negative exponential decay
functiondecay_linear()
Linear decay functiondecay_power()
. Inverse power decay functionLet’s first load the libraries used in this vignette:
library(accessibility)
library(data.table)
library(ggplot2)
library(sf)
To use accessibility
, you will need a pre-computed
travel cost matrix in long format combined with land-use data
(e.g. location of jobs, healthcare, population). Travel costs can be
presented in terms of travel times, distances or monetary costs. This
input data must be presented as a data.frame
containing the
columns with origin ids, destination ids, the travel cost between each
origin-destination pair, and the number of opportunities located in each
destination. Note that to to calculate
floating_catchment_area()
, your input data should also
include a column with the size of the population in each origin.
The data input should look similar to this:
<- system.file("extdata/ttm_bho.rds", package = "accessibility")
data_path <- readRDS(data_path)
ttm head(ttm)
#> from_id to_id travel_time population jobs schools
#> 1: 89a88cdb57bffff 89a88cdb57bffff 5.8 606 82 0
#> 2: 89a88cdb57bffff 89a88cdb597ffff 47.0 606 308 2
#> 3: 89a88cdb57bffff 89a88cdb5b3ffff 48.0 606 100 0
#> 4: 89a88cdb57bffff 89a88cdb5cfffff 47.0 606 109 0
#> 5: 89a88cdb57bffff 89a88cd909bffff 64.0 606 0 0
#> 6: 89a88cdb57bffff 89a88cd90b7ffff 59.0 606 480 0
This is a small sample data with public transport travel times and land use data for the city of Belo Horizonte (Brazil) included in the package and that we will be using to illustrate its functionalities.
If you would like to estimate such travel cost matrices, there are several computational packages to do that in R, such as: - r5r - dodgr - gtfsrouter - hereR - opentripplanner
time_to_closest()
allows you to easily calculate the
minimum travel cost accessibility. In the example below, the output
shows the minimum travel cost from each origin to the closet school and
the id of the destination where the school is located.
<- time_to_closest(data = ttm,
tmi opportunity_col = 'schools',
n_opportunities = 1,
travel_cost_col = 'travel_time',
by_col = 'from_id'
)
head(tmi)
#> from_id travel_cost destination
#> 1: 89a88cdb57bffff 28.0 89a88cdb53bffff
#> 2: 89a88cdb597ffff 5.8 89a88cdb597ffff
#> 3: 89a88cdb5b3ffff 11.0 89a88cdb5bbffff
#> 4: 89a88cdb5cfffff 13.0 89a88cdb5c7ffff
#> 5: 89a88cd909bffff 7.0 89a88cd9093ffff
#> 6: 89a88cd90b7ffff 6.0 89a88cd90a7ffff
The cumulative_time_cutoff()
functions calculates
traditional cumulative opportunity accessibility, indicating the number
of opportunities that are accessible in under a given travel cost
threshold. In this example, we estimate the number of jobs accessible in
up to 30 minutes.
<- cumulative_time_cutoff(
cum_cutoff data = ttm,
cutoff = 30,
opportunity_col = 'jobs',
travel_cost_col = 'travel_time',
by_col = 'from_id'
)
head(cum_cutoff)
#> from_id access
#> 1: 89a88cdb57bffff 22239
#> 2: 89a88cdb597ffff 36567
#> 3: 89a88cdb5b3ffff 42372
#> 4: 89a88cdb5cfffff 55571
#> 5: 89a88cd909bffff 26774
#> 6: 89a88cd90b7ffff 36991
cumulative_time_interval()
calculates the the time
interval cumulative accessibility measure. This is a novel accessibility
metric developed by Tomasiello et al. (forthcoming paper) to
mitigate the impacts of arbitrary choices of trip duration in
traditional threshold-based cumulative opportunity metrics. In the
example below, we calculate the average number of jobs accessible
considering multiple minute-by-minute time thresholds between 20 and 60
minutes.
<- cumulative_time_interval(
cum_interval data = ttm,
interval = c(20, 60),
stat = 'mean',
opportunity_col = 'jobs',
travel_cost_col = 'travel_time',
by_col = 'from_id'
)
head(cum_interval)
#> from_id access
#> 1: 89a88cdb57bffff 177395.5
#> 2: 89a88cdb597ffff 145321.4
#> 3: 89a88cdb5b3ffff 178228.1
#> 4: 89a88cdb5cfffff 229087.1
#> 5: 89a88cd909bffff 179526.9
#> 6: 89a88cd90b7ffff 204975.2
The gravity_access()
allows one to continuously discount
the weight of opportunities as travel costs become larger. See the vignette
on decay functions for more information on the decay functions
available in the package and how to use custom functions. In this case
here, we use a negative exponential function with a
decay_value
of 0.2
<- gravity_access(
grav_exp data = ttm,
opportunity_col = 'jobs',
decay_function = decay_exponential(decay_value = 0.2),
travel_cost_col = 'travel_time',
by_col = 'from_id'
)
head(grav_exp)
#> from_id access
#> 1: 89a88cdb57bffff 413.5854
#> 2: 89a88cdb597ffff 729.7845
#> 3: 89a88cdb5b3ffff 744.2263
#> 4: 89a88cdb5cfffff 886.9436
#> 5: 89a88cd909bffff 543.4047
#> 6: 89a88cd90b7ffff 1947.6067
The floating_catchment_area()
functions provides users
with floating catchment area (FCA) indicators that allow you to
calculate accessibility accounting for the competition of resources. The
use can use the parameter fca_metric
to specify which
indicator of the broad FCA family should be used. The package currently
supports two FCA metrics.
2SFCA was the first accessibility metric in the floating catchment area family. It was originally proposed by Luo & Wang (Luo and Wang 2003).
<- floating_catchment_area(
fca_2sfca data = ttm,
fca_metric = '2SFCA',
population_col = 'population',
opportunity_col = 'schools',
decay_function = decay_exponential(decay_value = 0.2),
travel_cost_col = 'travel_time',
orig_col = 'from_id',
dest_col = 'to_id'
)
head(fca_2sfca)
#> from_id access_2sfca
#> 1: 89a88cdb57bffff 0.000008219232
#> 2: 89a88cdb597ffff 0.000392296809
#> 3: 89a88cdb5b3ffff 0.000181524093
#> 4: 89a88cdb5cfffff 0.000099700375
#> 5: 89a88cd909bffff 0.000142171505
#> 6: 89a88cd90b7ffff 0.000221000580
The BFCA metric calculates accessibility accounting for competition effects while simultaneously correcting for issues of inflation of demand and service levels that are present in previous floating catchment area measures. It is the most recent FCA metric and it was originally proposed by Paez et al. (Paez, Higgins, and Vivona 2019) and named in Pereira et al. (Pereira et al. 2021).
<- floating_catchment_area(
fca_bfca data = ttm,
fca_metric = 'BFCA',
population_col = 'population',
opportunity_col = 'schools',
decay_function = decay_exponential(decay_value = 0.2),
travel_cost_col = 'travel_time',
orig_col = 'from_id',
dest_col = 'to_id'
)
head(fca_bfca)
#> from_id access_bfca
#> 1: 89a88cdb57bffff 0.000008953755
#> 2: 89a88cdb597ffff 0.000357273221
#> 3: 89a88cdb5b3ffff 0.000171592450
#> 4: 89a88cdb5cfffff 0.000121565261
#> 5: 89a88cd909bffff 0.000143809692
#> 6: 89a88cd90b7ffff 0.000203323698
If you have a spatial data with the geometries of your
origin/destination data set, you can easily merge
it with
the accessibility to map the results. Here is a quick example using
ggplot2
.
library(ggplot2)
library(sf)
library(data.table)
# load spatial data
<- system.file("extdata/grid_bho.rds", package = "accessibility")
grid <- readRDS(grid)
grid
# merge accessibility output to spatial data
<- merge(grid, cum_cutoff, by.x='id', by.y='from_id')
df
# for large data sets, this can be done much faster with `data.table` as follows:
<- setDT(grid)[cum_cutoff, on=c('id'='from_id'), access := i.access]
df2 <- st_sf(df2, crs = 4326)
df2
# plot
ggplot() +
geom_sf(data = df2, aes(fill = access), color=NA, alpha=0.9) +
labs(title = 'Employment accessibility by transit in under 30 min.',
fill='Number of jobs\naccessible') +
scale_fill_viridis_c() +
theme_void()
If you have any suggestions or want to report an error, please visit the package GitHub page.