---
title: "An Overview of Basic Features in spmodel"
author: "Michael Dumelle, Matt Higham, and Jay M. Ver Hoef"
header-includes:
   - \usepackage{amsmath,amsfonts,amssymb}
   - \usepackage{bm, bbm}
   - \usepackage{mathtools}
bibliography: '`r system.file("references.bib", package="spmodel")`'
output:
    pdf_document:
      number_sections: true
      toc: false
vignette: >
  %\VignetteIndexEntry{An Overview of Basic Features in spmodel}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
# # jss style
# knitr::opts_chunk$set(prompt=TRUE, echo = TRUE, highlight = FALSE, continue = " + ", comment = "")
# options(replace.assign=TRUE, width=90, prompt="R> ")

# rmd style
knitr::opts_chunk$set(collapse = FALSE, comment = "#>", warning = FALSE, message = FALSE)

# load packages
library(ggplot2)
library(spmodel)
```

# Introduction

The `spmodel` package is used to fit and summarize spatial models and make predictions at unobserved locations (Kriging). This vignette provides an overview of basic features in `spmodel`. We load `spmodel` by running
```{r, eval = FALSE}
library(spmodel)
```

If you use `spmodel` in a formal publication or report, please cite it. Citing `spmodel` lets us devote more resources to it in the future. We view the `spmodel` citation by running
```{r}
citation(package = "spmodel")
```

There are two additional `spmodel` vignettes:

* A detailed guide to `spmodel`: `vignette("guide", "spmodel")`
* Technical details regarding many functions: `vignette("technical", "spmodel")`

# The Data

Many of the data sets we use in this vignette are `sf` objects. `sf` objects are data frames (or tibbles) with a special structure that stores spatial information. They are built using the sf [@pebesma2018sf] package, which is installed alongside `spmodel`. We will use four data sets throughout this vignette:

* `moss`: An `sf` object with heavy metal concentrations in Alaska.
* `sulfate`: An `sf` object with sulfate measurements in the conterminous United States.
* `sulfate_preds`: An `sf` object with locations at which to predict sulfate measurements in the conterminous United States.
* `caribou`: A `tibble` (a special `data.frame`) for a caribou foraging experiment in Alaska.

We will create visualizations using ggplot2 [@wickham2016ggplot2], which we load by running
```{r, eval = FALSE}
library(ggplot2)
```

ggplot2 is only installed alongside `spmodel` when `dependencies = TRUE` in `install.packages()`, so check that it is installed before reproducing any visualizations in this vignette.

# Spatial Linear Models

Spatial linear models for a quantitative response vector $\mathbf{y}$ have spatially dependent random errors and are often parameterized as

\begin{equation*}
\mathbf{y} = \mathbf{X} \boldsymbol{\beta} + \boldsymbol{\tau} + \boldsymbol{\epsilon},
\end{equation*}

where $\mathbf{X}$ is a matrix of explanatory variables (usually including a column of 1's for an intercept), $\boldsymbol{\beta}$ is a vector of fixed effects that describe the average impact of $\mathbf{X}$ on $\mathbf{y}$, $\boldsymbol{\tau}$ is a vector of spatially dependent (correlated) random errors, and $\boldsymbol{\epsilon}$ is a vector of spatially independent (uncorrelated) random errors. The spatial dependence of $\boldsymbol{\tau}$ is explicitly specified using a spatial covariance function that incorporates the variance of $\boldsymbol{\tau}$, often called the partial sill, and a range parameter that controls the behavior of the spatial covariance. The variance of $\boldsymbol{\epsilon}$ is often called the nugget. 

Spatial linear models are fit in `spmodel` for point-referenced and areal data. Data are point-referenced when the elements in $\mathbf{y}$ are observed at point-locations indexed by x-coordinates and y-coordinates on a spatially continuous surface with an infinite number of locations. The `splm()` function is used to fit spatial linear models for point-referenced data (these are often called geostatistical models). Data are areal when the elements in $\mathbf{y}$ are observed as part of a finite network of polygons whose connections are indexed by a neighborhood structure. For example, the polygons may represent counties in a state who are neighbors if they share at least one boundary. The `spautor()` function is used to fit spatial linear models for areal data (these are often called spatial autoregressive models). This vignette focuses on spatial linear models for point-referenced data, though `spmodel`'s other vignettes discuss spatial linear models for areal data.

The `splm()` function has similar syntax and output as the commonly used `lm()` function used to fit non-spatial linear models. `splm()` generally requires at least three arguments:

* `formula`: a formula that describes the relationship between the response variable and explanatory variables.
    * `formula` uses the same syntax as the `formula` argument in `lm()`
* `data`: a `data.frame` or `sf` object that contains the response variable, explanatory variables, and spatial information.
* `spcov_type`: the spatial covariance type (`"exponential"`, `"spherical"`, `"matern"`, etc).

If `data` is an `sf` object, the coordinate information is taken from the object's geometry. If `data` is a `data.frame` (or `tibble`), then `xcoord` and `ycoord` are required arguments to `splm()` that specify the columns in `data` representing the x-coordinates and y-coordinates, respectively. `spmodel` uses the spatial coordinates "as-is," meaning that `spmodel` does not perform any projections. To project your data or change the coordinate reference system, use `sf::st_transform()`. If an `sf` object with polygon geometries is given to `splm()`, the centroids of each polygon are used to fit the spatial linear model.

Next we show the basic features and syntax of `splm()` using the Alaskan `moss` data. We study the impact of log distance to the road (`log_dist2road`) on log zinc concentration (`log_Zn`). We view the first few rows of the `moss` data by running
```{r}
moss
```

We can visualize the distribution of log zinc concentration (`log_Zn`) by running
```{r}
ggplot(moss, aes(color = log_Zn)) +
  geom_sf(size = 2) +
  scale_color_viridis_c()
```

Log zinc concentration appears highest in the middle of the spatial domain, which has a road running through it. We fit a spatial linear model regressing log zinc concentration on log distance to the road using an exponential spatial covariance function by running
```{r}
spmod <- splm(log_Zn ~ log_dist2road, data = moss, spcov_type = "exponential")
```

The estimation method is specified via the `estmethod` argument, which has a default value of `"reml"` for restricted maximum likelihood. Other estimation methods are `"ml"` for maximum likelihood, `"sv-wls"` for semivariogram weighted least squares, and `"sv-cl"` for semivariogram composite likelihood. 

Printing `spmod` shows the function call, the estimated fixed effect coefficients, and the estimated spatial covariance parameters. `de` is the estimated variance of $\boldsymbol{\tau}$ (the spatially dependent random error), `ie` is the estimated variance of $\boldsymbol{\epsilon}$ (the spatially independent random error), and `range` is the range parameter.

```{r}
print(spmod)
```

Next we show how to obtain more detailed summary information from the fitted model.

## Model Summaries

We summarize the fitted model by running
```{r}
summary(spmod)
```

Similar to summaries of `lm()` objects, summaries of `splm()` objects include the original function call, residuals, and a coefficients table of fixed effects. Log zinc concentration appears to significantly decrease with log distance from the road, as evidenced by the small p-value associated with the asymptotic z-test. A pseudo r-squared is also returned, which quantifies the proportion of variability explained by the fixed effects.

In the remainder of this subsection, we describe the broom [@robinson2021broom] functions `tidy()`, `glance()` and `augment()`. `tidy()` tidies coefficient output in a convenient `tibble`, `glance()` glances at model-fit statistics, and `augment()` augments the data with fitted model diagnostics.

We tidy the fixed effects by running
```{r}
tidy(spmod)
```

We glance at the model-fit statistics by running
```{r}
glance(spmod)
```

The columns of this `tibble` represent:

* `n`: The sample size
* `p`: The number of fixed effects (linearly independent columns in $\mathbf{X}$)
* `npar`: The number of estimated covariance parameters
* `value`: The value of the minimized objective function used when fitting the model
* `AIC`: The Akaike Information Criterion (AIC)
* `AICc`: The AIC with a small sample size correction
* `logLik`: The log-likelihood
* `deviance`: The deviance
* `pseudo.r.squared`: The pseudo r-squared

The `glances()` function can be used to glance at multiple models at once. Suppose we wanted to compare the current model, which uses an exponential spatial covariance, to a new model without spatial covariance (equivalent to a model fit using `lm()`). We do this using `glances()` by running
```{r}
lmod <- splm(log_Zn ~ log_dist2road, data = moss, spcov_type = "none")
glances(spmod, lmod)
```

The much lower AIC and AICc for the spatial linear model indicates it is a much better fit to the data. Outside of `glance()` and `glances()`, the functions `AIC()`, `AICc()`, `logLik()`, `deviance()`, and `pseudoR2()` are available to compute the relevant statistics.

We augment the data with diagnostics by running
```{r}
augment(spmod)
```

The columns of this tibble represent:

* `log_Zn`: The log zinc concentration.
* `log_dist2road`: The log distance to the road.
* `.fitted`: The fitted values (the estimated mean given the explanatory variable values).
* `.resid`: The residuals (the response minus the fitted values).
* `.hat`: The leverage (hat) values.
* `.cooksd`: The Cook's distance
* `.std.residuals`: Standardized residuals
* `geometry`: The spatial information in the `sf` object.

By default, `augment()` only returns the variables in the data used by the model. All variables from the original data are returned by setting `drop = FALSE`. Many of these model diagnostics can be visualized by running `plot(spmod)`. We can learn more about `plot()` in `spmodel` by running `help("plot.spmodel", "spmodel")`. 

## Prediction (Kriging)

Commonly a goal of a data analysis is to make predictions at unobserved locations. In spatial contexts, prediction is often called Kriging. Next we use the `sulfate` data to build a spatial linear model of sulfate measurements in the conterminous United States with the goal of making sulfate predictions (Kriging) for the unobserved locations in `sulfate_preds`.

We visualize the distribution of `sulfate` by running
```{r}
ggplot(sulfate, aes(color = sulfate)) +
  geom_sf(size = 2) +
  scale_color_viridis_c(limits = c(0, 45))
```

Sulfate appears spatially dependent, as measurements are highest in the Northeast and lowest in the Midwest and West.

We fit a spatial linear model regressing sulfate on an intercept using a spherical spatial covariance function by running
```{r}
sulfmod <- splm(sulfate ~ 1, data = sulfate, spcov_type =  "spherical")
```

We make predictions at the locations in `sulfate_preds` and store them as a new variable called `preds` in the `sulfate_preds` data set by running
```{r}
sulfate_preds$preds <- predict(sulfmod, newdata = sulfate_preds)
```

We visualize these predictions by running
```{r}
ggplot(sulfate_preds, aes(color = preds)) +
  geom_sf(size = 2) +
  scale_color_viridis_c(limits = c(0, 45))
```

These predictions have similar sulfate patterns as in the observed data (predicted values are highest in the Northeast and lowest in the Midwest and West). Next we remove the model predictions from `sulfate_preds` before showing how `augment()` can be used to obtain the same predictions:
```{r}
sulfate_preds$preds <- NULL
```

While `augment()` was previously used to augment the original data with model diagnostics, it can also be used to augment the `newdata` data with predictions:
```{r}
augment(sulfmod, newdata = sulfate_preds)
```
Here `.fitted` represents the predictions.

Confidence intervals for the mean response or prediction intervals for the predicted response can be obtained by specifying the `interval` argument in `predict()` and `augment()`:
```{r}
augment(sulfmod, newdata = sulfate_preds, interval = "prediction")
```
By default, `predict()` and `augment()` compute 95% intervals, though this can be changed using the `level` argument.

While the fitted model in this example only used an intercept, the same code is used for prediction with fitted models having explanatory variables. If explanatory variables were used to fit the model, the same explanatory variables must be included in `newdata` with the same names they have in `data`. If `data` is a `data.frame`, coordinates must be included in `newdata` with the same names as they have in `data`. If `data` is an `sf` object, coordinates must be included in `newdata` with the same geometry name as they have in `data`. When using projected coordinates, the projection for `newdata` should be the same as the projection for `data`.

## An Additional Example

We now use the `caribou` data from a foraging experiment conducted in Alaska to show an application of `splm()` to data stored in a `tibble` (`data.frame`) instead of an `sf` object. In `caribou`, the x-coordinates are stored in the `x` column and the y-coordinates are stored in the `y` column. We view the first few rows of `caribou` by running
```{r}
caribou
```

We fit a spatial linear model regressing nitrogen percentage (`z`) on water presence (`water`) and tarp cover (`tarp`) by running
```{r}
cariboumod <- splm(z ~ water + tarp, data = caribou,
                   spcov_type = "exponential", xcoord = x, ycoord = y)
```

An analysis of variance can be conducted to assess the overall impact of the `tarp` variable, which has three levels (clear, shade, and none), and the `water` variable, which has two levels (water and no water). We perform an analysis of variance by running
```{r}
anova(cariboumod)
```
There seems to be significant evidence that at least one tarp cover impacts nitrogen. Note that, like in `summary()`, these p-values are associated with an asymptotic hypothesis test (here, an asymptotic Chi-squared test).

# Function Glossary

Here we list some commonly used `spmodel` functions.

* `AIC()`: Compute the AIC.
* `AICc()`: Compute the AICc.
* `anova()`: Perform an analysis of variance.
* `augment()`: Augment data with diagnostics or new data with predictions.
* `coef()`: Return coefficients.
* `confint()`: Compute confidence intervals.
* `cooks.distance()`: Compute Cook's distance.
* `covmatrix()`: Return covariance matrices.
* `deviance()`: Compute the deviance.
* `esv()`: Compute an empirical semivariogram.
* `fitted()`: Compute fitted values.
* `glance()`: Glance at a fitted model.
* `glances()`: Glance at multiple fitted models.
* `hatvalues()`: Compute leverage (hat) values.
* `logLik()`: Compute the log-likelihood.
* `loocv()`: Perform leave-one-out cross validation.
* `model.matrix()`: Return the model matrix ($\mathbf{X}$).
* `plot()`: Create fitted model plots.
* `predict()`: Compute predictions and prediction intervals.
* `pseudoR2()`: Compute the pseudo r-squared.
* `residuals()`: Compute residuals.
* `spautor()`: Fit a spatial linear model for areal data (i.e., spatial autoregressive model).
* `spautorRF()`: Fit a random forest spatial residual model for areal data.
* `splm()`: Fit a spatial linear model for point-referenced data (i.e., geostatistical model).
* `splmRF()`: Fit a random forest spatial residual model for point-referenced data.
* `sprnorm()`: Simulate spatially correlated normal (Gaussian) random variables.
* `summary()`: Summarize fitted models.
* `tidy()`: Tidy fitted models.
* `varcomp()`: Compare variance components.
* `vcov()`: Compute variance-covariance matrices of estimated parameters.

For a full list of `spmodel` functions alongside their documentation, see the documentation manual.
Documentation for methods of generic functions that are defined outside of `spmodel` can be found
by running `?generic.spmodel` (e.g., `?fitted.spmodel`, `?predict.spmodel`, `?summary.spmodel`, etc.).

# References {.unnumbered}

<div id="refs"></div>
