Locationallocation
locationallocation: an R package to solve Maximal Coverage Location-Allocation problems using geospatial data
Install / Use
/learn @giacfalk/LocationallocationREADME
locationallocation <a href = "https://giacfalk.github.io/locationallocation/"><img src = "man/figures/logo.png" align="right" width="120" /></a>
<!-- quarto render --> <!-- Install the package before rendering this file: `devtools::install()` --> <!-- badges: start --> <!-- badges: end -->Overview
Assessing and planning infrastructure and service networks, given a dispersed demand, limited capacity, accessibility targets, and concerns about spatial justice, is a central policy challenge. Problems of this type are commonly referred to as Maximal Coverage Location-Allocation (MCLA) spatial optimization problems.
locationallocation is an R package that provides tools for solving
MCLA problems with geospatial data. It builds on widely used spatial
libraries in R, follows tidyverse
principles,
and integrates seamlessly with the broader tidyverse
ecosystem. The package can generate travel-time
maps and optimize the placement of facilities or infrastructure
according to accessibility criteria, which can be weighted by one or
more variables or by a user-defined function.
Potential applications of the package extend to the domains of public infrastructure assessment and planning (public services provision, e.g. transport, social services, healthcare, parks), urban environmental and climate risk reduction interventions, logistics and hubs allocation, commercial and strategic decisions.
If you find this project useful, please consider giving it a star!
Installation
You can install locationallocation using the
remotes package:
# install.packages(remotes)
remotes::install_github("giacfalk/locationallocation")
A CRAN version of the package is planned for the near future.
Usage
To use the package, start by loading it to your R session using the
library function:
library(locationallocation)
As an example, we demonstrate how the package can address urban-scale climate risk through infrastructure assessment and geospatial planning. For this demonstration, we use the demo datasets included with the package.
These datasets include the coordinates of public drinking water
fountains (blue dots) in Naples, Italy
(naples_fountains);
a gridded population raster from the Global Human Settlement Layer
(GHSL) Population
Grid
(GHS-POP)
(naples_population);
a 100-meter resolution heat hazard map, representing the number of days
with Wet-Bulb Globe
Temperature
above 25°C during 2008–2017, obtained from the
UrbClim model
(naples_hot_days);
and the city’s administrative boundaries
(naples_shape).

We can use the
traveltime()
function to create a map of current accessibility to the facility points
(represented by the sf object
naples_fountains)
within the specified geographical boundaries. The function allows the
user to select a travel mode (walking or fastest route) and an output
spatial resolution in meters, achieved through dissevering spatial
downscaling techniques.
traveltime_data <-
naples_fountains |>
traveltime(
bb_area = naples_shape,
dowscaling_model_type = "lm",
mode = "walk",
res_output = 100
)
Once
traveltime()
has completed, the resulting layer can be visualized using the
traveltime_plot()
function.
traveltime_data |>
traveltime_plot(
bb_area = naples_shape,
facilities = naples_fountains,
contour_traveltime = 15
)

We can also generate a summary plot and compute statistics using the
output of the
traveltime()
function, together with a demand raster (e.g., population density) and a
specified time threshold, using the
traveltime_stats
function:
traveltime_data |>
traveltime_stats(
demand = naples_population,
breaks = c(5, 10, 15, 30),
objectiveminutes = 15
)
#> ℹ 85.45148% of coverage within the 15 minutes threshold.

We can now use the
allocation()
function to optimize the placement of new water fountains, ensuring that
(virtually) everyone (i.e., the full extent of the raster layer
specified by the demand parameter) can reach one within 15 minutes, as
defined by the objectiveminutes parameter:
allocation_data <-
naples_population |>
allocation(
bb_area = naples_shape,
facilities = naples_fountains,
traveltime = traveltime_data,
weights = NULL,
objectiveminutes = 15,
objectiveshare = 0.99,
heur = "max",
approach = "norm",
exp_demand = 1,
exp_weights = 1
)
#> ✔ Target coverage share of 99% attained with 28 facilities within the 15
#> minutes threshold. The achieved coverage share is 99.03953%.
allocation_data |> allocation_plot(naples_shape)

Note that it is also possible to solve an allocation problem using the
weights parameter, which assigns greater relative importance or
priority to areas where demand overlaps with weighting factors defined
by another raster layer, such as exposure to hot days, as shown in the
following example:
allocation_data <-
naples_population |>
allocation(
bb_area = naples_shape,
facilities = naples_fountains,
traveltime = traveltime_data,
weights = naples_hot_days, # <--- Changed
objectiveminutes = 15,
objectiveshare = 0.99,
heur = "max",
approach = "norm",
exp_demand = 1,
exp_weights = 1
)
#> ✔ Target coverage share of 99% attained with 25 facilities within the 15
#> minutes threshold. The achieved coverage share is 99.16903%.
allocation_data |> allocation_plot(naples_shape)

It is also possible to apply normalization and exponentiation to
different demand and weighting layers, enhancing their relative
influence on the allocation, using the approach, exp_demand, and
exp_weights parameters (see the function
documentation
for details):
allocation_data <-
naples_population |>
allocation(
bb_area = naples_shape,
facilities = naples_fountains,
traveltime = traveltime_data,
weights = naples_hot_days,
objectiveminutes = 15,
objectiveshare = 0.99,
heur = "max",
approach = "norm",
exp_demand = 2, # <--- Changed
exp_weights = 1
)
#> ✔ Target coverage share of 99% attained with 9 facilities within the 15
#> minutes threshold. The achieved coverage share is 99.15597%.
allocation_data |> allocation_plot(naples_shape)

A variant of the allocation problem arises when the set of candidate locations for new facilities is discrete, rather than continuous across the study area as in the previous example.
In this case, the user must provide a set of candidate points via the
candidate parameter of the
allocation_discrete()
function, along with the maximum number of facilities that can be
selected (n_fac parameter). The function applies a quasi-optimality
heuristic based on a randomization approach, where the number of
replications (n_samples parameter) gradually approaches the global
optimum, although computational time increases linearly. As with the
continuous allocation problem, a weight layer and normalization and
exponentiation parameters can also be specified.
library(sf)
allocation_data <-
naples_population |>
allocation_discrete(
bb_area = naples_shape,
candidate = naples_shape |> st_sample(20),
facilities = naples_fountains,
n_fac = 5,
n_samples = 100,
traveltime = travelt
Related Skills
node-connect
350.1kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
109.9kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
350.1kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
qqbot-media
350.1kQQBot 富媒体收发能力。使用 <qqmedia> 标签,系统根据文件扩展名自动识别类型(图片/语音/视频/文件)。
