Spatial Modelling with inlabru
December 15, 2025
Space is inherent to all ecological processes, influencing dynamics such as migration, dispersal, and species interactions. A primary goal in ecology is to understand how these processes shape species distributions and dynamics across space.
Many natural processes take place in space
increased resolution \(\leadsto\) large, complex datasets \(\leadsto\) complex spatial models required
often inaccessible to practitioners (literature aimed at statisticians)
methodology not always linked to applications
models too simple to reflect real-life data
difficult to apply without expertise in spatial stats and computational statistics
we shall see that inlabru can help with this.
We can distinguish three types of spatial data structures
Areal data
Geostatistical data
Point pattern data
We can distinguish three types of spatial data structures
Areal data
In areal data our measurements are summarised across a set of discrete, non-overlapping spatial units.
Geostatistical data
Point pattern data
We can distinguish three types of spatial data structures
Areal data
Geostatistical data
In geostatistical data, measurements of a continuous process are taken at a set of fixed locations.
Point pattern data
We can distinguish three types of spatial data structures
Areal data
Geostatistical data
Point pattern data
In point pattern data we record the locations where events occur (e.g. trees in a forest, earthquakes) and the coordinates of such occurrences are our data.
Discrete space: - Data on a spatial grid (areal data)
Continuous space: - Geostatistical (geo-referenced) data - Spatial point pattern data
Model components are used to reflect spatial dependence structures in discrete and continuous space.
Imagine we have animal counts in each region. We can model them as Poisson
\[ y_i \sim \mathrm{Poisson}(e^{\eta_i}) \] How do we model the linear predictor \(\eta_i\)?
\[ \eta_i = \beta_0 + \mathbf{x}'\beta + u_i ~~~ u_i \overset{iid}{\sim} N(0,\sigma^2_i) \]
Imagine we have animal counts in each region. We can model them as Poisson
\[ y_i \sim \mathrm{Poisson}(e^{\eta_i}) \] How do we model the linear predictor \(\eta_i\)?
Imagine we have animal counts in each region. We can model them as Poisson
\[ y_i \sim \mathrm{Poisson}(e^{\eta_i}) \] How do we model the linear predictor \(\eta_i\)?
\[ \eta_i = \beta_0 + \mathbf{x}'\beta + u_i ~~~ u_i \overset{iid}{\sim} N(0,Q^{-1}) \]
An areal process (or lattice process) is a stochastic process defined on a set of regions that form a partition of our region of interest \(D\).
Let \(B_1, \ldots B_m\) be our set of \(m\) distinct regions such that: \[\bigcup\limits_{i=1}^m \hspace{1mm}B_i = D.\]
Here we require that our regions are non-overlapping, with \[B_i \cap B_j = \emptyset.\]
Then our areal process is simply the stochastic process \[\{Z(B_i); i=1,\ldots,m\}.\]
Each of our regions \(B_i\) has a set of other nearby which can be considered neighbours
We might expect that areas have more in common with their neighbours.
Therefore, we can construct dependence structures based on the principle that neighbours are correlated and non-neighbours are uncorrelated.
However, we need to come up with a sensible way of defining what a neighbour is in this context.
There are many different ways to define a region’s neighbours.
The most common ones fall into two main categories - those based on borders, and those based on distance.
Common borders
Assume that regions which share a border on a map are neighbours.
Simple and easy to implement
Treats all borders the same, regardless of length, which can be unrealistic.
Areas very close together are not neighbours if there is even a small gap between them.
Distance-based
Assume that regions which are a within a certain distance of each other area neighbours.
What distance do you choose? How do you decide that?
Where do you measure from? (e.g., nearest border or a central point).
Once we have identified a set of neighbours using our chosen method, we can use this to account for spatial correlation.
We construct a neighbourhood matrix (or proximity matrix), which defines how each of our \(m\) regions relate to each other.
Let \(W\) denote an \(m \times m\) matrix where the \((i,j)\)th entry, \(w_{ij}\) denotes the proximity between regions \(B_i\) and \(B_j\).
Note
The values of this matrix can be discrete (which regions are neighbours) or continuous (how far apart are the regions).
By far the most common approach is to use a binary neighbourhood matrix, \(W\), denoted by
\[ \begin{aligned} w_{ij} &= 1 \hspace{2mm} \mbox{ if areas} (B_i, B_j) \mbox{ are neighbours.}\\ w_{ij} &= 0 \hspace{2mm} \mbox{ otherwise.} \end{aligned} \]
Dependencies structures are described through this spatial weights matrix
Binary matrices are used for their simplicity
Gauss Markov random field (GMRF) is
GMRFs are key to the INLA approach – and inlabru:
An example of a GMRF is the the Besag model a.k.a. Intrinsic Conditional Autoregressive (ICAR) model. The conditional distribution for \(u_i\) is
\[ u_i|\mathbf{u}_{-i} \sim N\left(\frac{1}{d_i}\sum_{j\sim i}u_j,\frac{1}{d_i\tau_u}\right) \]
\(\mathbf{u}_{-i} = (u_i,\ldots,u_{i-1},u_{i+1},\ldots,u_n)^T\)
\(\tau_u\) is the precision parameter (inverse variance).
\(d_i\) is the number of neighbours
The mean of \(u_i\) is equivalent to the the mean of the effects over all neighbours, and the precision is proportional to the number of neighbours.
The joint distribution is given by:
\[ \mathbf{u}|\tau_u \sim N\left(0,\frac{1}{\tau_u}Q^{-1}\right), \]
Where \(Q\) denotes the precision matrix defined as
\[ Q_{i,j} = \begin{cases} d_i, & i = j \\ -1, & i \sim j \\ 0, &\text{otherwise} \end{cases} \]
This structure matrix directly defines the neighbourhood structure and is sparse.
The ICAR model accounts only for spatially structured variability and does not include a limiting case where no spatial structure is present.
We typically add an unstructured random effect \(z_i|\tau_v \sim N(0,\tau_{z}^{-1})\)
The resulting model \(v_i = u_i + z_i\) is known as the Besag-York-Mollié model (BYM)
The structured spatial effect is controlled by \(\tau_u\) which control the degree of smoothing:
Higher \(\tau_u\) values lead to stronger smoothing (less spatial variability).
Lower \(\tau_u\) values allow for greater local variation.
In the next example we will illustrate how to fit this model using inlabru.
In this example we model the number of respiratory hospitalisations across Intermediate Zones (IZ) that make up the Greater Glasgow and Clyde health board in Scotland.
In epidemiology, disease risk is assessed using Standardized Mortality Ratios (SMR):
\[ SMR_i = \dfrac{Y_i}{E_i} \]
- Stage 1: We assume the responses are Poisson distributed: \[ \begin{aligned}y_i|\eta_i & \sim \text{Poisson}(E_i\lambda_i)\\\text{log}(\lambda_i) = \color{#FF6B6B}{\boxed{\eta_i}} & = \color{#FF6B6B}{\boxed{\beta_0 + \beta_1 \mathrm{pm10} + u_i + z_i} }\end{aligned} \]
- Stage 2: \(\eta_i\) is a linear function of four components: an intercept, pm10 effect , a spatially structured effect \(u\) and an unstructured iid random effect \(z\):
\[ \eta_i = \beta_0 + u_i + z_i \]
- Stage 3: \(\{\tau_{z},\tau_u\}\): Precision parameters for the random effects
The latent field is \(\mathbf{x}= (\beta_0, \beta_1, u_1, u_2,\ldots, u_n,z_1,...)\), the hyperparameters are \(\boldsymbol{\theta} = (\tau_u,\tau_z)\), and must be given a prior.
The Model
\[ \begin{aligned} y_i|\eta_t & \sim \text{Poisson}(E_i\lambda_i)\\ \text{log}(\lambda_i) = \eta_i & = \color{#FF6B6B}{\boxed{\beta_0}} + \color{#FF6B6B}{\boxed{\beta_1 \mathrm{pm10}}} + \color{#FF6B6B}{\boxed{u_i}} + \color{#FF6B6B}{\boxed{z_i}} \end{aligned} \]
The code
# define model component
cmp = ~ Intercept(1) + pm10(pm10, model = "linear") +
space(space, model = "besag", graph = Q) +
iid(space, model = "iid")
# define model predictor
eta = observed ~ Intercept + space + iid
# build the observation model
lik = bru_obs(formula = formula,
family = "poisson",
E = expected,
data = resp_cases)
# fit the model
fit = bru(cmp, lik)The Model
\[ \begin{aligned} y_i|\eta_t & \sim \text{Poisson}(E_i\lambda_i)\\ \text{log}(\lambda_i) = \color{#FF6B6B}{\boxed{\eta_i}} & = \color{#FF6B6B}{\boxed{\beta_0 + \beta_1 \mathrm{pm10} + u_i + z_i}} \end{aligned} \]
The code
# define model component
cmp = ~ Intercept(1) + pm10(pm10, model = "linear")
space(space, model = "besag", graph = Q) +
iid(space, model = "iid")
# define model predictor
eta = observed ~ Intercept + space + iid
# build the observation model
lik = bru_obs(formula = formula,
family = "poisson",
E = expected,
data = resp_cases)
# fit the model
fit = bru(cmp, lik)The Model
\[ \begin{aligned} \color{#FF6B6B}{\boxed{y_i|\eta_t}} & \sim \color{#FF6B6B}{\boxed{\text{Poisson}(E_i\lambda_i)}}\\ \text{log}(\lambda_i) = \eta_i & = \beta_0 + \beta_1 \mathrm{pm10} + u_i + z_i \end{aligned} \]
The code
# define model component
cmp = ~ Intercept(1) + pm10(pm10, model = "linear")
space(space, model = "besag", graph = Q) +
iid(space, model = "iid")
# define model predictor
eta = observed ~ Intercept + space + iid
# build the observation model
lik = bru_obs(formula = formula,
family = "poisson",
E = expected,
data = resp_cases)
# fit the model
fit = bru(cmp, lik)The Model
\[ \begin{aligned} y_i|\eta_t & \sim \text{Poisson}(E_i\lambda_i)\\ \text{log}(\lambda_i) = \eta_i & = \beta_0 + \beta_1 \mathrm{pm10} + u_i + z_i \end{aligned} \]
The code
# define model component
cmp = ~ Intercept(1) + pm10(pm10, model = "linear")
space(space, model = "besag", graph = Q) +
iid(space, model = "iid")
# define model predictor
eta = observed ~ Intercept + space + iid
# build the observation model
lik = bru_obs(formula = formula,
family = "poisson",
E = expected,
data = resp_cases)
# fit the model
fit = bru(cmp, lik)Posterior summaries
| mean | 0.025quant | 0.975quant | |
|---|---|---|---|
| Intercept | −1.52 | −1.91 | −1.12 |
| pm10 | 0.09 | 0.07 | 0.12 |
| Precision for space | 2.82 | 2.28 | 3.45 |
| Precision for iid | 21,825.18 | 1,420.88 | 85,676.44 |
Estimated relative risks
Measurements of an a spatial continuous variable of interest at a set of fixed locations.
This could be data from samples taken in locations across a region of interest (e.g., water depth in a lake) or from monitoring stations as part of a network (e.g., air pollution).
In each of these cases, our goal is to estimate the value of our variable across the entire space and/or to model the relationship with covariates.
If we have a process that is occurring everywhere in space, it is natural to try to model it using some sort of function.
\[ \mathbf{z} = (z(\mathbf{s}_1),\ldots,z(\mathbf{s}_m)) \sim \mathcal{N}(0,\Sigma), \] where \(\Sigma_{ij} = \mathrm{Cov}(z(\mathbf{s}_i),z(\mathbf{s}_j))\) is a dense \(m \times m\) matrix.
Stationary random fields
A GRF is stationary if:
has mean zero.
the covariance between two points depends only on the distance and direction between those points.
It is isotropic if the covariance only depends on the distance between the points.
The goal: approximate the GRF using a triangulated mesh via the so-called SPDE approach.
The SPDE approach represents the continuous spatial process as a continuously indexed Gaussian Markov Random Field (GMRF)
\[ c_{\nu}(d;\sigma,\rho) = \sigma^2\frac{2^{1-\nu}}{\Gamma(\nu)}\left(\sqrt{8\nu}\frac{d}{\rho}\right)^{\nu}K_{\nu}\left(\sqrt{8\nu}\frac{d}{\rho}\right) \]
Penalized Complexity (PC) priors proposed by Simpson et al. (2017) allow us to control the amount of spatial smoothing and avoid overfitting.
F. Lindgren, H. Rue, and J. Lindström. An explicit link between Gaussian fields and Gaussian Markov random fields: The SPDE approach (with discussion). In: Journal of the Royal Statistical Society, Series B 73.4 (2011), pp. 423–498.
H. Bakka, H. Rue, G. A. Fuglstad, A. Riebler, D. Bolin, J. Illian, E. Krainski, D. Simpson, and F. Lindgren. Spatial modelling with R-INLA: A review. In: WIREs Computational Statistics 10:e1443.6 (2018). (Invited extended review). DOI: 10.1002/wics.1443.
E. T. Krainski, V. Gómez-Rubio, H. Bakka, A. Lenzi, D. Castro-Camilio, D. Simpson, F. Lindgren, and H. Rue. Advanced Spatial Modeling with Stochastic Partial Differential Equations using R and INLA. Github version . CRC press, Dec. 20
We call spatial Markov models defined on a mesh SPDE models.
SPDE models have 3 parts
A mesh
A range parameter \(\kappa\)
A precision parameter \(\tau\)
Lets see how this is done in practice!
In the next example, we will explore data on the Pacific Cod (Gadus macrocephalus) from a trawl survey in Queen Charlotte Sound. The
Stage 1 Model for the response \[ y(s)|\eta(s)\sim\text{Binom}(1, p(s)) \]
Stage 2 Latent field model \[ \eta(s) = \text{logit}(p(s)) = \beta_0 + f( x(s)) + \omega(s) \]
Stage 3 Hyperparameters
Stage 1 Model for the response \[ y(s)|\eta(s)\sim\text{Binom}(1, p(s)) \]
Stage 2 Latent field model \[ \eta(s) = \text{logit}(p(s)) = \beta_0 + \beta_1 x(s) + \omega(s) \]
Stage 3 Hyperparameters
First, we need to create the mesh used to approximate the random field.
max.edge for maximum triangle edge lengthsoffset for inner and outer extensions (to prevent edge effects)cutoff to avoid overly small triangles in clustered areasAll random field models need to be discretised for practical calculations.
The SPDE models were developed to provide a consistent model definition across a range of discretisations.
We use finite element methods with local, piecewise linear basis functions defined on a triangulation of a region of space containing the domain of interest.
Deviation from stationarity is generated near the boundary of the region.
The choice of region and choice of triangulation affects the numerical accuracy.
If the mesh is too fine \(\rightarrow\) heavy computation
If the mesh is to coarse \(\rightarrow\) not accurate enough
Some guidelines
Create triangulation meshes with fm_mesh_2d():
edge length should be around a third to a tenth of the spatial range
Move undesired boundary effects away from the domain of interest by extending to a smooth external boundary:
Use a coarser resolution in the extension to reduce computational cost (max.edge=c(inner, outer)), i.e., add extra, larger triangles around the border
Use a fine resolution (subject to available computational resources) for the domain of interest (inner correlation range) and avoid small edges ,i.e., filter out small input point clusters (0 \(<\) `cutoff \(<\) inner)
Coastlines and similar can be added to the domain specification in fm_mesh_2d() through the boundary argument.
simplify the border
We use the inla.spde2.pcmatern to define the SPDE model using PC priors through the following probability statements
\(P(\rho < 100) = 0.5\)
\(P(\sigma > 1) = 0.5\)
The Model
\[\begin{aligned} y(s)|\eta(s) & \sim\text{Binom}(1, p(s))\\ \eta(s) & = \color{#FF6B6B}{\boxed{\beta_0}} + \color{#FF6B6B}{\boxed{ f(x(s))}} + \color{#FF6B6B}{\boxed{ \omega(s)}}\\ \end{aligned}\]Simple feature collection with 232 features and 2 fields
Geometry type: POINT
Dimension: XY
Bounding box: xmin: 343.0617 ymin: 5639.857 xmax: 576.9152 ymax: 5837.211
Projected CRS: +proj=utm +zone=9 +datum=WGS84 +no_defs +type=crs +units=km
# A tibble: 232 × 3
depth present geometry
<dbl> <dbl> <POINT [km]>
1 201 1 (446.4752 5793.426)
2 212 1 (446.4594 5800.136)
3 220 0 (448.5987 5801.687)
# ℹ 229 more rows
The code
# define model component
cmp = ~ -1 + Intercept(1) + depth_smooth(log(depth), model='rw2') +
space(geometry, model = spde_model)
# define model predictor
eta = present ~ Intercept + depth_smooth + space
# build the observation model
lik = bru_obs(formula = eta,
data = pcod_sf,
family = "binomial")
# fit the model
fit = bru(cmp, lik)The Model
\[\begin{aligned} y(s)|\eta(s) & \sim\text{Binom}(1, p(s))\\ \color{#FF6B6B}{\boxed{\eta(s)}} & = \color{#FF6B6B}{\boxed{\beta_0 + f(x(s)) + \omega(s)}}\\ \end{aligned}\]Simple feature collection with 232 features and 2 fields
Geometry type: POINT
Dimension: XY
Bounding box: xmin: 343.0617 ymin: 5639.857 xmax: 576.9152 ymax: 5837.211
Projected CRS: +proj=utm +zone=9 +datum=WGS84 +no_defs +type=crs +units=km
# A tibble: 232 × 3
depth present geometry
<dbl> <dbl> <POINT [km]>
1 201 1 (446.4752 5793.426)
2 212 1 (446.4594 5800.136)
3 220 0 (448.5987 5801.687)
# ℹ 229 more rows
The code
# define model component
cmp = ~ -1 + Intercept(1) + depth_smooth(log(depth), model='rw2') +
space(geometry, model = spde_model)
# define model predictor
eta = present ~ Intercept + depth_smooth + space
# build the observation model
lik = bru_obs(formula = eta,
data = pcod_sf,
family = "binomial")
# fit the model
fit = bru(cmp, lik)The Model
\[\begin{aligned} \color{#FF6B6B}{\boxed{y(s)|\eta(s)}} & \sim \color{#FF6B6B}{\boxed{\text{Binom}(1, p(s))}}\\ \eta(s) & = \beta_0 + f(x(s)) + \omega(s)\\ \end{aligned}\]Simple feature collection with 232 features and 2 fields
Geometry type: POINT
Dimension: XY
Bounding box: xmin: 343.0617 ymin: 5639.857 xmax: 576.9152 ymax: 5837.211
Projected CRS: +proj=utm +zone=9 +datum=WGS84 +no_defs +type=crs +units=km
# A tibble: 232 × 3
depth present geometry
<dbl> <dbl> <POINT [km]>
1 201 1 (446.4752 5793.426)
2 212 1 (446.4594 5800.136)
3 220 0 (448.5987 5801.687)
# ℹ 229 more rows
The code
# define model component
cmp = ~ -1 + Intercept(1) + depth_smooth(log(depth), model='rw2') +
space(geometry, model = spde_model)
# define model predictor
eta = present ~ Intercept + depth_smooth + space
# build the observation model
lik = bru_obs(formula = eta,
data = pcod_sf,
family = "binomial")
# fit the model
fit = bru(cmp, lik)Many of the ecological and environmental processes of interest can be represented by a spatial point process or can be viewed as an aggregation of one.
Consider a fixed geographical region \(A\).
The set of locations at which events occur are denoted by \(\mathbf{s} = (\mathbf{s}_1, \ldots, \mathbf{s}_n)\).
We let \(N(A)\) be a random variable which represents the total number of events in every subset of region \(A\).
Our primary interest is in measuring where events occur, so the locations are our data.
A simplestpoint process model is the homogeneous Poisson process (HPP).
The likelihood of a point pattern \(\mathbf{y} = \left[ \mathbf{s}_1, \ldots, \mathbf{s}_n \right]^\intercal\) distributed as a HPP with intensity \(\lambda\) and observation window \(\Omega\) is
\[ p(\mathbf{y} | \lambda) \propto \lambda^n e^{ \left( - |\Omega| \lambda \right)} , \]
\(|\Omega|\) is the size of the observation window.
\(\lambda\) is the expected number of points per unit area.
\(|\Omega|\lambda\) the total expected number of points in the observation window.
The inhomogeneous Poisson process has a spatially varying intensity \(\lambda(\mathbf{s})\).
The likelihood in this case is
\[ p(\mathbf{y} | \lambda) \propto \exp \left( -\int_\Omega \lambda(\mathbf{s}) \mathrm{d}\mathbf{s} \right) \prod_{i=1}^n \lambda(\mathbf{s}_i). \]
If the case of an HPP the integral in the likelihood can easily be computed as \(\int_\Omega \lambda(\mathbf{s}) \mathrm{d}\mathbf{s} =|\Omega|\lambda\)
For IPP, integral in the likelihood has to be approximated numerically as a weighted sum.
This integral is approximated as \(\sum_{j=1}^J w_j \lambda(\mathbf{s}_j)\)
\(w_j\) are the integration weights
\(\mathbf{s}_j\) are the quadrature locations.
This serves two purposes:
Approximating the integral
re-writing the inhomogeneous Poisson process likelihood as a regular Poisson likelihood.
The idea behind the trick to rewrite the approximate likelihood is to introduce a dummy vector \(\mathbf{z}\) and an integration weights vector \(\mathbf{w}\) of length \(J + n\)
\[\mathbf{z} = \left[\underbrace{0_1, \ldots,0_J}_\text{quadrature locations}, \underbrace{1_1, \ldots ,1_n}_{\text{data points}} \right]^\intercal\]
\[\mathbf{w} = \left[ \underbrace{w_1, \ldots, w_J}_\text{quadrature locations}, \underbrace{0_1, \ldots, 0_n}_\text{data points} \right]^\intercal\]
Then the approximate likelihood can be written as
\[ \begin{aligned} p(\mathbf{z} | \lambda) &\propto \prod_{i=1}^{J + n} \eta_i^{z_i} \exp\left(-w_i \eta_i \right) \\ \eta_i &= \log\lambda(\mathbf{s}_i) = \mathbf{x}(s)'\beta \end{aligned} \]
This is similar to a product of Poisson distributions with means \(\eta_i\), exposures \(w_i\) and observations \(z_i\).
This is the basis for the implementation of Cox process models in inlabru, which can be specified using family = "cp".
\[ \log~\lambda(s)= \mathbf{x}(s)'\beta + \xi(s) \]
The events are then assumed to be independent given the covariates and \(\xi(s)\) - a GMRF with Matérn covariance.
inlabru has implemented some integration schemes that are especially well suited to integrating the intensity in models with an SPDE effect.
In this example we model the location of forest fires in the Castilla-La Mancha region of Spain between 1998 and 2007.
We are now going to use the elevation as a covariate to explain the variability of the intensity \(\lambda(s)\) over the domain of interest and a spatially structured SPDE model.
\[ \log\lambda(s) = \beta_0 + \beta_1 \text{elevation}(s) + \xi(s) \]
The IPP Model \[ \begin{aligned} p(\mathbf{y} | \lambda) & \propto \exp \left( -\int_\Omega \lambda(\mathbf{s}) \mathrm{d}\mathbf{s} \right) \prod_{i=1}^n \lambda(\mathbf{s}_i) \\ \eta(s) & = \log ~\lambda(s) = \beta_0 + x(s) \end{aligned} \] The code
The LGCP Model
\[ \begin{aligned} p(\mathbf{y} | \lambda) & \propto \exp \left( -\int_\Omega \lambda(\mathbf{s}) \mathrm{d}\mathbf{s} \right) \prod_{i=1}^n \lambda(\mathbf{s}_i) \\ \eta(s) & = \log(\lambda(s)) = \color{#FF6B6B}{\boxed{\beta_0}} + \color{#FF6B6B}{\boxed{ x(s)}} + \color{#FF6B6B}{\boxed{ \omega(s)}}\\ \end{aligned} \]
The code
# define model component
cmp = ~ Intercept(1) + elev(elev_raster, model = "linear") +
space(geometry, model = spde_model)
# define model predictor
eta = geometry ~ Intercept + elev + space
# build the observation model
lik = bru_obs("cp",
formula = eta,
data = pp,
ips = ips)
# fit the model
fit = bru(cmp, lik)The LGCP Model
\[ \begin{aligned} p(\mathbf{y} | \lambda) & \propto \exp \left( -\int_\Omega \lambda(\mathbf{s}) \mathrm{d}\mathbf{s} \right) \prod_{i=1}^n \lambda(\mathbf{s}_i) \\ \color{#FF6B6B}{\boxed{\eta(s)}} & = \log(\lambda(s)) = \color{#FF6B6B}{\boxed{\beta_0 + x(s) + \omega(s)}}\\ \end{aligned} \]
The code
# define model component
cmp = ~ Intercept(1) + elev(elev_raster, model = "linear") +
space(geometry, model = spde_model)
# define model predictor
eta = geometry ~ Intercept + elev + space
# build the observation model
lik = bru_obs("cp",
formula = eta,
data = pp,
ips = ips)
# fit the model
fit = bru(cmp, lik)The LGCP Model
\[ \begin{aligned} \color{#FF6B6B}{\boxed{p(\mathbf{y} | \lambda)}} & \propto \exp \left( -\int_\Omega \lambda(\mathbf{s}) \mathrm{d}\mathbf{s} \right) \prod_{i=1}^n \lambda(\mathbf{s}_i) \\ \eta(s) & = \log(\lambda(s)) = \beta_0 + x(s) + \omega(s)\\ \end{aligned} \]
The code
# define model component
cmp = ~ Intercept(1) + elev(elev_raster, model = "linear") +
space(geometry, model = spde_model)
# define model predictor
eta = geometry ~ Intercept + elev + space
# build the observation model
lik = bru_obs("cp",
formula = eta,
data = pp,
ips = ips)
# fit the model
fit = bru(cmp, lik)The LGCP Model
\[ \begin{aligned} p(\mathbf{y} | \lambda) & \propto \exp \left( -\int_\Omega \lambda(\mathbf{s}) \mathrm{d}\mathbf{s} \right) \prod_{i=1}^n \lambda(\mathbf{s}_i) \\ \eta(s) & = \log(\lambda(s)) = \beta_0 + x(s) + \omega(s)\\ \end{aligned} \]
The code
# define model component
cmp = ~ Intercept(1) + elev(elev_raster, model = "linear") +
space(geometry, model = spde_model)
# define model predictor
eta = geometry ~ Intercept + elev + space
# build the observation model
lik = bru_obs("cp",
formula = eta,
data = pp,
ips = ips)
# fit the model
fit = bru(cmp, lik)Model Predictions