Decay functions

Rafael H. M. Pereira, Daniel Herszenhut

2022-06-29

1. Introduction

Some functions of the accessibility package, such as floating_catchment_area() and gravity_access(), use decay functions to continuously discount the weight of opportunities as travel costs become larger. For convenience, the package currently includes four decay functions discussed in (Kwan 1998). See the implemented functions below. Additionally, the package also allows users to pass any custom decay function that converts travel cost t_ij to an impedance factor (see section 3).

2. Currently available decay functions

2.1 Binary decay function

Also known as ‘step’ decay function, commonly used in cumulative opportunity measures.

\[ \begin{aligned} f(t_{ij})= \left\{ \begin{array}{ll} 1 & \quad \text{for }t_{ij} \leq T \\ 0 & \quad \text{for }t_{ij} > T \end{array} \right.\\ \end{aligned} \]

Where \(t_{ij}\) is the travel cost between origin i and destination j; and \(T\) is the cutoff of maximum travel cost.

2.2 Linear decay function

\[ \begin{aligned} f(t_{ij})= \left\{ \begin{array}{ll} (1 - t_{ij}/ T) & \quad \text{for }t_{ij} \leq T \\ 0 & \quad \text{for }t_{ij} > T \end{array} \right.\\ \end{aligned} \]

Where \(t_{ij}\) is the travel cost between origin i and destination j; and \(T\) is the cutoff of maximum travel cost.

2.3 Negative exponential.

\[ \begin{aligned} f(t_{ij})= e^{(-\beta t_{ij})} \end{aligned} \]

Where: \(t_{ij}\) is the travel cost between origin i and destination j; and \(\beta\) is the decay_value that tells the speed of decay.

2.4 Inverse power

\[ \begin{aligned} f(t_{ij})= \left\{ \begin{array}{ll} 1 & \quad \text{for } t_{ij}\leq 1 \\ t_{ij}^{-\beta} & \quad \text{for }t_{ij} > 1 \end{array} \right.\\ \end{aligned} \]

Where \(t_{ij}\) is the travel cost between origin i and destination j; and \(\beta\) is the decay_value that tells the speed of decay.

Quick demonstration of how these decay functions look like

library(accessibility)
library(data.table)
library(ggplot2)
#> Warning: package 'ggplot2' was built under R version 4.1.3

# Generate inputs
vec <- 0:100
decay_value <- 0.2
cutoff <- 50

# Return functions
step        <- decay_binary(cutoff=cutoff)
linear      <- decay_linear(cutoff=cutoff)
exponential <- decay_exponential(decay_value=decay_value)
power       <- decay_power(decay_value = decay_value)

df <- data.table(minutes       = vec,
                 binary        = step(vec),
                 linear        = linear(vec),
                 exponential   = exponential(vec),
                 inverse_power = power(vec)
                 )

# reshape the data to long format
df2 <- data.table::melt.data.table(data = df, 
                                   id.vars = 'minutes', 
                                   variable.name = 'decay_function', 
                                   value.name = 'impedance_factor')

# plot
ggplot() +
  geom_line(data=df2, aes(x=minutes, y=impedance_factor, color=decay_function), show.legend = FALSE) +
  facet_wrap(.~decay_function, ncol = 2) +
  theme_minimal()

3. Using a custom decay function

Let’s use the sample data available in the accessibility package o demonstrate how you could use a custom decay function. Let’s load the data first.


# load input data
data_path <- system.file("extdata/ttm_bho.rds", package = "accessibility")
ttm <- readRDS(data_path)
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

Now let’s create a very simple custom decay function that uses a parameter k to convert the travel cost t_ij between origin i and destination j into an impedance factor.

# create custom decay function
custom_decay_fun <- function(k) {
  impedance <- function(t_ij) {
    f <- 1 / t_ij ^ k
    return(f)
  }
}

You can use your custom_decay_fun() inside the floating_catchment_area() and gravity_access() functions like this:

# calculate gravity-based accessibility
grav_custom <- gravity_access(
                  data = ttm,
                  opportunity_col = 'jobs',
                  decay_function = custom_decay_fun(k=0.5),
                  travel_cost_col = 'travel_time',
                  by_col = 'from_id'
                  )

head(grav_custom)
#>            from_id   access
#> 1: 89a88cdb57bffff 73936.42
#> 2: 89a88cdb597ffff 72088.42
#> 3: 89a88cdb5b3ffff 74512.95
#> 4: 89a88cdb5cfffff 78470.00
#> 5: 89a88cd909bffff 74298.70
#> 6: 89a88cd90b7ffff 77323.59

References

Kwan, Mei-Po. 1998. “Space-Time and Integral Measures of Individual Accessibility: A Comparative Analysis Using a Point-Based Framework.” Geographical Analysis 30 (3): 191–216.