max_coverage
solves the binary optimisation problem known as the
"maximal covering location problem" as described by Church
(http://www.geo .ucsb.edu/~forest/G294download/MAX_COVER_RLC_CSR.pdf).
This package was implemented to make it easier to solve this problem in the
context of the research initially presented by Chan et al
(http://circ.ahajournals.org/content/127/17/1801.short) to identify ideal
locations to place AEDs.
Usage
max_coverage(
existing_facility,
proposed_facility,
user,
distance_cutoff,
n_added,
d_existing_user = NULL,
d_proposed_user = NULL,
solver = "glpk"
)
Arguments
- existing_facility
data.frame containing the facilities that are already in existing, with columns names lat, and long.
- proposed_facility
data.frame containing the facilities that are being proposed, with column names lat, and long.
- user
data.frame containing the users of the facilities, along with column names lat, and long.
- distance_cutoff
numeric indicating the distance cutoff (in metres) you are interested in. If a number is less than distance_cutoff, it will be 1, if it is greater than it, it will be 0.
- n_added
the maximum number of facilities to add.
- d_existing_user
Optional distance matrix between existing facilities and users. Default distances are direct (geospherical ellipsoidal) distances; this allows alternative measures such as street-network distances to be submitted (see Examples).
- d_proposed_user
Option distance matrix between proposed facilities and users (see Examples).
- solver
character "glpk" (default) or "lpSolve". "gurobi" is currently in development, see https://github.com/njtierney/maxcovr/issues/25.
Examples
library(dplyr)
# already existing locations
york_selected <- york |> filter(grade == "I")
# proposed locations
york_unselected <- york |> filter(grade != "I")
mc_result <- max_coverage(existing_facility = york_selected,
proposed_facility = york_unselected,
user = york_crime,
distance_cutoff = 100,
n_added = 20)
mc_result
#>
#> -------------------------------------------
#> Model Fit: maxcovr fixed location model
#> -------------------------------------------
#> model_used: max_coverage
#> existing_facility: york_selected
#> proposed_facility: york_unselected
#> user: york_crime
#> distance_cutoff: 100
#> n_added: 20
#> d_existing_user: lpSolve
#> -------------------------------------------
summary(mc_result)
#>
#> -------------------------------------------
#> Model Fit: maxcovr fixed location model
#> -------------------------------------------
#> Distance Cutoff: 100m
#> Facilities:
#> Added: 20
#> Coverage (Previous):
#> # Users: 540 (339)
#> Proportion: 0.2977 (0.1869)
#> Distance (m) to Facility (Previous):
#> Avg: 886 (1400)
#> SD: 986 (1597)
#> -------------------------------------------
# get the facilities chosen
mc_result$facility_selected
#> [[1]]
#> # A tibble: 20 × 7
#> long lat object_id desig_id pref_ref name grade
#> <dbl> <dbl> <int> <chr> <int> <chr> <chr>
#> 1 -1.09 54.0 5978 DYO1383 462917 NA II
#> 2 -1.08 54.0 5909 DYO1297 463072 NA II
#> 3 -1.08 54.0 5872 DYO1244 463186 NA II
#> 4 -1.08 54.0 5847 DYO1216 463242 NA II
#> 5 -1.12 54.0 5759 DYO1108 463434 FORMER JUNIOR SCHOOL BUILDING … II
#> 6 -1.08 54.0 5748 DYO1096 463469 NA II
#> 7 -1.08 54.0 5745 DYO1093 463465 NA II
#> 8 -1.08 54.0 5739 DYO1086 463457 CHURCH OF ST GEORGE AND ATTACH… II
#> 9 -1.10 54.0 5642 DYO960 463695 NA II
#> 10 -1.09 53.9 5606 DYO920 463771 PRESS STAND AT YORK RACECOURSE II
#> 11 -1.06 54.0 5592 DYO903 463788 NA II
#> 12 -1.07 54.0 5588 DYO899 463782 NA II
#> 13 -1.08 54.0 5529 DYO829 463938 CHURCH OF ST THOMAS II
#> 14 -1.08 54.0 5454 DYO705 464133 NUMBERS 45-51 (ODD) AND ATTACH… II
#> 15 -1.03 54.0 5373 DYO1644 NA War Memorial II
#> 16 -1.12 54.0 5349 DYO572 464451 POPPLETON ROAD SCHOOL II
#> 17 -1.08 54.0 5328 DYO544 464508 WOODS MILL II
#> 18 -1.00 54.0 3215 DYO1581 491367 STOCKTON GRANGE AND ATTACHED O… II
#> 19 -1.08 54.0 3213 DYO1580 490659 NEW CHAPEL AT ST JOHN'S COLLEGE II
#> 20 -1.08 54.0 4803 DYO1734 NA The Swan Public House II
#>
# get the users affected
mc_result$user_affected
#> [[1]]
#> # A tibble: 201 × 16
#> user_id user_chosen facility_id distance category persistent_id date lat
#> <dbl> <int> <dbl> <dbl> <chr> <chr> <chr> <dbl>
#> 1 1 1 66 166. anti-soci… 62299914865f… 2016… 54.0
#> 2 5 1 25 536. anti-soci… 6139f131b724… 2016… 54.0
#> 3 13 1 6 2334. anti-soci… c2aac5cdf98e… 2016… 54.0
#> 4 14 1 2 12687. anti-soci… c0908b075c68… 2016… 54.1
#> 5 15 1 24 620. anti-soci… 40c8c061c48b… 2016… 54.0
#> 6 21 1 60 1286. anti-soci… 45ce21c8785e… 2016… 53.9
#> 7 23 1 NA NA NA NA NA NA
#> 8 24 1 NA NA NA NA NA NA
#> 9 27 1 NA NA NA NA NA NA
#> 10 29 1 2 375. anti-soci… db6cacd76d97… 2016… 54.0
#> # ℹ 191 more rows
#> # ℹ 8 more variables: long <dbl>, street_id <chr>, street_name <chr>,
#> # context <chr>, id <chr>, location_type <chr>, location_subtype <chr>,
#> # outcome_status <chr>
#>
# get the summaries
mc_result$summary
#> [[1]]
#> # A tibble: 2 × 8
#> n_added distance_within n_cov pct_cov n_not_cov pct_not_cov dist_avg dist_sd
#> <dbl> <dbl> <int> <dbl> <int> <dbl> <dbl> <dbl>
#> 1 0 100 339 0.187 1475 0.813 1400. 1597.
#> 2 20 100 540 0.298 1274 0.702 886. 986.
#>
# Example of street-network distance calculations
if (FALSE) { # \dontrun{
library(dodgr)
net <- dodgr_streetnet_sf ("york england") |>
weight_streetnet (wt_profile = "foot")
from <- match_points_to_graph (v, york_selected[, c ("long", "lat")])
to <- match_points_to_graph (v, york_crime[, c ("long", "lat")])
d_existing_user <- dodgr_dists (net, from = from, to = to)
from <- match_points_to_graph (v, york_unselected[, c ("long", "lat")])
d_proposed_user <- dodgr_dists (net, from = from, to = to)
mc_result <- max_coverage(existing_facility = york_selected,
proposed_facility = york_unselected,
user = york_crime,
distance_cutoff = 100,
n_added = 20,
d_existing_user = d_existing_user,
d_proposed_user = d_proposed_user)
} # }