# Standardized effect sizes

#### Neander M. Heming, Flávio Mota, and Gabriela Alves-Ferreira

#### 2023-08-10

Source:`vignettes/SES.Rmd`

`SES.Rmd`

## Contents

After understanding how the spatial null model algorithms work
(`vignette("spatial-null-models")`

), let’s see how to create
multiple null models and test for the effect size using
`SESraster()`

.

## Standardized effect size

Standardized effect size (SES) is a measure of the magnitude of the
studied effect. It indicates the direction and the degree that the
effect departures from the null model. SESraster uses Cohen’s *d*
(Cohen 1988), which is measured as the
difference between the observed pattern and the average of *n*
randomized observations divided by the standard deviation of the
randomized observations \(SES =
(Obs-mean(Null))/sd(Null)\).

## Calculating SES

### Random species generation

First, we will create some random species distributions using the
package `terra`

.

```
library(SESraster)
#> This is SESraster 0.7.0
#> If you use SESraster, please cite in your publications. See:
#> citation("SESraster")
library(terra)
#> terra 1.7.39
# creating random species distributions
f <- system.file("ex/elev.tif", package="terra")
r <- rast(f)
set.seed(510)
r <- rast(lapply(1:18,
function(i, r, mn, mx){
app(r, function(x, t){
sapply(x, function(x, t){
x<max(t) & x>min(t)
}, t = t)
}, t = sample(seq(mn, mx), 2))
}, r = r, mn = minmax(r)[1]+10, mx = minmax(r)[2]-10))
names(r) <- paste("sp", 1:nlyr(r))
plot(r)
```

With the distributions in hand, we can perform the spatial randomizations.

### SES with spatial randomization

First we need a function that computes the desired metric. The function must work with spatial data. Just to exemplify, we are creating a function to compute the mean of presences and absences (1/0) within each cell. You probably wants to use a more ecologically meaningful function, but here is just an example of use.

```
appmean <- function(x, ...){
terra::app(x, "mean", ...)
}
```

Now, to compute SES, we will compute our desired metric by sending
our function `appmean()`

to `SESraster()`

through
`FUN`

argument. We also randomize the original data by
`species`

using the `bootspat_naive()`

algorithm
and passing the argument `random="species"`

through
`spat_alg_args`

.

```
ses.sp <- SESraster(r, FUN = appmean,
spat_alg = "bootspat_naive", spat_alg_args = list(random = "species"),
aleats = 5)
plot(ses.sp)
```

Compute metric and SES using `bootspat_naive()`

and
randomize by `site`

changing the argument to
`random="site"`

in `spat_alg_args`

.

```
ses.st <- SESraster(r, FUN = appmean,
spat_alg = "bootspat_naive", spat_alg_args = list(random = "site"),
aleats = 5)
plot(ses.st)
```

#### Passing arguments to `FUN`

It is also possible to send arguments to the function that calculates
the desired metric (`FUN`

). It can be done by sending a list
of arguments through `FUN_args`

.

```
## let's create some missing values for layer/species 1
r2 <- r
set.seed(10)
cellsNA <- terra::spatSample(r2, 30, na.rm = TRUE, cells = TRUE, values = FALSE)
r2[cellsNA][1] <- NA
# plot(r)
set.seed(10)
sesNA <- SESraster(r2, FUN = appmean, FUN_args = list(na.rm = FALSE),
spat_alg = "bootspat_naive", spat_alg_args=list(random = "species"),
aleats = 5)
head(sesNA[cellsNA])
#> Observed.mean Null_Mean.mean Null_SD.mean SES.mean
#> 1 NA NA NA NA
#> 2 NA NA NA NA
#> 3 NA NA NA NA
#> 4 NA NA NA NA
#> 5 NA NA NA NA
#> 6 NA NA NA NA
plot(sesNA)
```

Notice that NAs can be ignored by the `appmean()`

function
by using `FUN_args = list(na.rm = TRUE)`

:

```
set.seed(10)
ses.woNA <- SESraster(r2, FUN = appmean, FUN_args = list(na.rm = TRUE),
spat_alg = "bootspat_naive", spat_alg_args=list(random = "species"),
aleats = 5)
head(ses.woNA[cellsNA])
#> Observed.mean Null_Mean.mean Null_SD.mean SES.mean
#> 1 0.11764706 0.3882353 0.08921030 -3.0331502
#> 2 0.41176471 0.3882353 0.08921030 0.2637522
#> 3 0.41176471 0.4117647 0.09300817 0.0000000
#> 4 0.05882353 0.3647059 0.07669650 -3.9882179
#> 5 0.35294118 0.4000000 0.07669650 -0.6135720
#> 6 0.52941176 0.4941176 0.08921030 0.3956283
plot(ses.woNA)
```

### SES from species trait randomization

In addition to the spatial randomizations, it is possible to create a
null model by randomizing a parameter (i.e. argument) of the metric
passed to FUN. This is useful, for example, to randomize a species trait
(e.g. branch length) that is used to compute the metric. In the example
below the function `appsv()`

uses the argument
`lyrv`

to compute the fictional metric. We also create some
fictional values for the trait.

```
## example with `Fa_alg`
appsv <- function(x, lyrv, na.rm = FALSE, ...){
sumw <- function(x, lyrv, na.rm, ...){
ifelse(all(is.na(x)), NA,
sum(x*lyrv, na.rm=na.rm, ...))
}
stats::setNames(terra::app(x, sumw, lyrv = lyrv, na.rm=na.rm, ...), "sumw")
}
set.seed(10)
trait <- sample(100:2000, nlyr(r))
trait
#> [1] 590 1772 1453 467 1583 538 1707 1561 1546 1634 1846 443 1394 242 1037
#> [16] 1578 1998 1029
```

In this exapmle, no spatial randomization will be performed, only
trait randomization. To select the *trait* to be randomized, pick
the desired argument of `FUN_args`

using
`Fa_sample`

and the name of the desired argument (here
“lyrv”). Then select a function, here “sample” is used. It is also
possible to send arguments to the function in `Fa_alg`

through `Fa_alg_args`

. It works in the same way that
arguments are sent to `FUN`

and `spat_alg`

through
`FUN_args`

and `spat_alg_args`

.

In this first
example it is performed a trait sampling **without**
replacement.

```
set.seed(10)
ses <- SESraster(r, FUN = appsv,
FUN_args = list(lyrv = trait, na.rm = TRUE),
Fa_sample = "lyrv",
Fa_alg = "sample", Fa_alg_args = list(replace = FALSE),
aleats = 5)
plot(ses)
```

In this second example it is performed a trait sampling
**with** replacement by passing `replace = TRUE`

through `Fa_alg_args`

.

```
set.seed(10)
ses <- SESraster(r, FUN = appsv,
FUN_args = list(lyrv = trait, na.rm = TRUE),
Fa_sample = "lyrv",
Fa_alg = "sample", Fa_alg_args = list(replace = TRUE),
aleats = 5)
plot(ses)
```