In this exercise we will compare some results from two different strategies to access landscape multiscale information:
We will build two objects, nest.ls
and dec.ls
, retaining nested and decoupled multiscale rasters, respectively.
#if installing is needed: #devtools::install_github("wilsonfrantine/landscapeDecoupler") library(landscapeDecoupler) library(raster)
We'll first define some objects that will be needed to extract landscape information from our raster file.
In this example with euglossini dataset, we'll explore buffers (b
) from 500 m to 3000 m with a regular interval (but it doesn't have to be) of 500 m; so: 500 m, 1000 m, 1500 m, 2000 m, 2500 m and 3000 m.
b <- c(500,1000,1500, 2000, 2500, 3000)
Then we will bring in a raster (r
) with the whole landscape we will explore in this example
r <- raster(system.file("extdata/raster.grd", package = "landscapeDecoupler"))
Now we can read some sampling sites from a shape file.
IMPORTANT: It is required you provied a field in shape files called "id" which will be used as unique identifier.
p <- read_points(system.file("extdata/pnts.shp", package = "landscapeDecoupler"), type="shp")
Note:
r
andp
are both native object inlandscapeDecoupler
, so you can access this same data by typingr
orp
in your console or code.
To check if everything loads properly, we can look at the plot.
plot(r) points(p, pch=19) plot(buffer(p, b[length(b)]), add=T)
nest.ls <- nestedscales(r, p , b)
Plotting scales for the first site:
multiplot(nest.ls, pallete = "viridis")
dec.ls <- decouple(r, p, b)
plotting
multiplot(dec.ls$p01, pallete ="viridis")
In landscapeDecouple
it is quite simple to retrive metrics from multiscale objects taking advantage of the package landscapemetrics
(hereafter lsm
). We can use the function calc_lsm
to apply any metric implemented in lsm
:
For the nested landscape approache
nest.lsm <- calc_lsm(nest.ls, metric=c("shdi", "pland")) tail(nest.lsm)
For the decoupled approach
dec.lsm <- calc_lsm(dec.ls, metric=c("shdi", "pland")) tail(dec.lsm)
First, let's take a look at how the landscape metrics behave in both multiscale strategies.
In order to do so, we will first combine both data frames (bind_rows()
) to make it easier to plot.
library("dplyr") # Herein I'm using the pipe ( %>% ) operator by importing dplyr library. # If you don't know it, take a look at Rstudio and tydiverse documentation. # The pipe make the code easier for humans to read it. # you can look at the actions from left to right taking what is happening # at left and aplying the function at the right of the pipe operator. combined.lsm <- nest.lsm %>% mutate(., strategy="nested") %>% bind_rows(., mutate(dec.lsm, strategy="decoupled")) %>% mutate(., site = as.factor(site), layer = as.factor(layer), level = as.factor(level), class = as.factor(class), metric = as.factor(metric), strategy = factor(strategy, levels = c("nested", "decoupled") ) ) combined.lsm %>% head()
Now we can load the ggplot2 and create our firs plot. In this plot, I've filtered the ggplot data by taking only lines with "pland" as metrics in combined.lsm
dataset.
We will then compare the mean and standard deviation of the "pland" (proportion of each) across the different scales we have.
library(ggplot2) # To rename the subplots with classes names instead of its values class.codes <- system.file("extdata/colors.txt", package = "landscapeDecoupler") %>% read.table( header = T, sep = "\t") %>% filter(value %in% levels(combined.lsm$class)) %>% pull(name, value) #Plotting... ggplot( data = combined.lsm %>% filter(metric=="pland") %>% group_by(strategy), mapping = aes(x=layer, y=value, color=strategy, fill=strategy) )+ stat_summary(fun.data = "mean_se", size=0.2)+ labs(title="Class cover proportion: Nested Vs Decoupled")+ facet_wrap(facets = "class", scales = "free_y", labeller = as_labeller(class.codes))+ theme( axis.text.x = element_text(angle=90) )+ scale_fill_manual( values = rep(rgb(1,1,1,0), 2) )
This picture shows the cumulative percentage of the landscape class cover throughout the scales. Notice that they all sum to 100% in each scale, so 50 means 50%, 0.6 is equal to 0.6% and so on...
It is interesting to notice that the decouple strategy is more sensitive to metrics variance between scales. The nested strategy, on the other hand, is always smoother. Since the “nested approach” accumulates the presence of the class in the previous scales, it will be null or suffer with subtle changes quite rarely. Whether this property shall be faced as advantage or disadvantage depends on the purpose and nature of the final analysis.
What about heterogeneity?
We can also look at a more complex metrics. Heterogeneity in this scope means how “complex” a landscape might be. In this very example we took the landscape Shannon index as a proxy of heterogeneity since it considers both presence and proportion of the classes in the landscape.
We can plot it pretty much like in the previous plot but filtering the combined.ls
by metric=="shdi"
.
ggplot( data = combined.lsm %>% filter(metric=="shdi") %>% group_by(layer, strategy), mapping = aes(x=layer, y=value, fill=strategy))+ geom_boxplot()+ labs(x="scales in meters", y="Shannon Diversity index", title="Heterogeneity throughout scales: Nested Vs Decoupled strategies")
As we can see, heterogeneity does not have a clear pathway across the landscapes in any strategy. That somehow derivates from the multifactorial nature of the metric, which depends on both number and “quantity” of landscape components (classes).
Nonetheless the decoupled strategy seems to bring more variation for this metric as well. It is expected since nested scales will share components and its variances as it progressively goes throughout the different scale sizes.
Up to here, we've observed that the different strategies resulted in different measurements for the landscape components. However, is it enough to bring different patterns when analyzing the relationship between metrics and biological variables?
Measuring the relationship between landscape components and biological variables across scales is quite useful to understanding ecological process. The multifit
approach is quite straightforward on that and landscapeDecoupler
has it natively implemented. We can make it very quickly with the following pipeline:
The landscapeDecouple
has a native object with an example data called euglossini
. Users can take a look at it just typing "euglossini" in the console:
euglossini
This dataset comprehends some community data of “orchid bees” (Apidae: Euglossini; details in Carneiro et al. 2021 ). It has five biological variables (columns 3 to 7) and 15 sampling sites (rows). In this example we'll look at the first two variables ( "Richness" and "Abundance" ).
IMPORTANT: the first column (site) is required for any data you will analyze and must have the same values as the "id" sampling sites in the shape file you used to extract landscape scales. Otherwise, several parts of the code will fail.
The very first step is to get things together for our model. Therefore, we must merge the metrics we just extracted (in nest.lsm
and dec.lsm
) with our biodata, euglossini
.
The multifit
function expect a very specific structure in a data frame with sampling sites as rows and "biodata+scales" as columns.
The lsm_calc()
output as we saw in nest.lsm
and dec.lsm
are both long format data. You can also use your own pipeline to get it ready for the multifit
function, but we have a very straightforward function for that.
The lsm2multifit
function can convert and connect tables with metrics and biodata just as expected by multifit
. You just need to set the dataframe with metrics (lsm
) and biological response table (biodata
). You must also set the level of the metrics and which metrics you want to extract. The id.col
specify the name of the column that matches the sampling sites in both lsm and biodata tables. It is the "site" by the default.
To the code:
## Nested # Merging biodata and heterogeneity nest.mfit.shdi <- lsm2multifit(lsm = nest.lsm,biodata =euglossini, level= "landscape", metrics="shdi", id.col = "site") # Same for forest cover nest.mfit.fcov <- lsm2multifit(lsm = nest.lsm,biodata =euglossini, level= "class", class=3, metrics="pland", id.col = "site") ## Decoupled # Merging biodata and heterogeneity dec.mfit.shdi <- lsm2multifit(lsm = dec.lsm, biodata=euglossini, level= "landscape", metrics="shdi", id.col = "site") # Same for forest cover dec.mfit.fcov <- lsm2multifit(lsm = dec.lsm, biodata=euglossini, level= "class", class=3, metrics="pland", id.col = "site") head(dec.mfit.fcov)
We have now four objects storing tables for the Shannon index ("shdi") and proportion of each class in the landscape ("pland"). Each strategy, decoupled and nested, has its own copy of these metrics.
To run multifit now is quite easy. You just have to follow the same as usual. Take a look at the code below:
predictors <- c("X500", "X1000","X1500","X2000","X2500","X3000") #As an alternative you can grab the "predictos" names with this: #get.scales.names(nest.mfit.shdi) multifit( mod = "lm", multief = predictors, data = nest.mfit.shdi, formula = Richness ~ multief, xlab = "scales", criterion = "R2")
Quite simple, isn't?
We have done quite a few things since we started. So, lets remind why we got here.
Our main purpose was to compare two different multiscale strategies ( decoupled and nested ) looking at the scale of effect. We retrieved two different metrics from landscape using these different approaches. So now we can apply the multifit and compare the R2 and see if they tell us different stories about the data.
Nested: Richness Vs Heterogeneity
predictors <- get.scales.names(nest.mfit.shdi) multi.nest.het.rich <- multifit( mod = "lm", multief = predictors, data = nest.mfit.shdi, formula = Richness ~ multief, xlab = "scales", criterion = "R2")
Decoupled: Richness Vs Heterogeneity
multi.dec.het.rich <- multifit( mod = "lm", multief = predictors, data = dec.mfit.shdi, formula = Richness ~ multief, xlab = "scales", criterion = "R2")
As we can see, we may have different interpretations about the scale of effect depending on which approach we take. In a nested approach landscape components will accumulate as we go through the scales (inner to out). Hence, the scale of effect will also accumulate the effect of the previous, as we can see at the first plot. The cumulated effect is then identified at the buffer with 2500 meters.
On the other hand, when we look at the decoupled approach, we can see the specific response in each actual scale. In such an approach, landscape components do not accumulate as the buffers size "increase", so the metrics, and therefore the relationship between biological response and landscape metrics are relative only to that slice of land. We can see that the metric from the buffer with 1500 meters has a stronger relationship with biological responses than its neighbor scales.
We will not go any further into the discussions about what should means a scale of effect or whether coupled or decoupled approach would better represent any concept of it, but it is interesting to notice how can we lose information overlooking one of these two approaches.
Let's see what happens for a different landscape atribute variable, the forest coverage...
Nested approach:
predictors <- get.scales.names(nest.mfit.shdi) multi.nest.fcov.rich <- multifit( mod = "lm", multief = predictors, data = nest.mfit.fcov, formula = Richness ~ multief, xlab = "scales", criterion = "R2")
Decoupled approach:
get.scales.names(nest.mfit.shdi) multi.dec.fcov.rich <- multifit( mod = "lm", multief = predictors, data = dec.mfit.fcov, formula = Richness ~ multief, xlab = "scales", criterion = "R2")
As we can see Richness and Forest Cover do not seem to have a very strong relationship since R2 is quite close to 0 in both approaches. Nonethelless, the decoupled approach seems to be a bit more sensitive, as we can see by the higher R2 levels and the subtle change in R2 variation through scale against the smooth one in the nested approach.
Moreover, while X2000 and X2500 seem to be less important in the nested strategy, the decoupled strategy display a more prominent e equal response for the larger scales. That is because the very nature of the nested strategy, wherein the residual effect of the previous smaller scale noises the effect next one. As we can see, in this case the heterogeneity has no relationship with abundance in the smaller scales, but this change in the larger ones. Since nested approach acumulate the landscape components from the smaller ones this lack of relationship is also inherited from the larger scales. This effect is always expected regardless of the strength or direction of the relationship.
We can now take a closer look at a different biological variable, the abundance. Since we have the dataset for the two metrics (shdi and pland / fcov) with all biological variables, we only need to change the formula in the function.
Nested: Abundance VS Heterogeneity
predictors <- get.scales.names(nest.mfit.shdi) multi.nest.het.abund <- multifit( mod = "lm", multief = predictors, data = nest.mfit.shdi, formula = Abundance ~ multief, xlab = "scales", criterion = "R2")
Decoupled: Abundance VS Heterogeneity
multi.dec.het.abund <- multifit( mod = "lm", multief = predictors, data = dec.mfit.shdi, formula = Abundance ~ multief, xlab = "scales", criterion = "R2")
In this comparison we don't see much since heterogeneity usually explain less than 10% of euglossini abundance in this dataset. We must bear in mind that we tested no requirements of linear models, and all comparisons are just illustrative. We are not looking at the best models, only the trend between two strategies over the same dataset.
Nonetheless, we can see the same noisy effect as we described for Richness VS Forest Cover above.
Let's see if the same happens for Abundance VS Forest Cover:
Nested: Abundance VS Forest Cover
predictors <- get.scales.names(dec.mfit.fcov) multi.nest.fcov.abund <- multifit( mod = "lm", multief = predictors, data = nest.mfit.fcov, formula = Abundance ~ multief, xlab = "scales", criterion = "R2")
Decoupled: Abundance VS Forest Cover
multi.dec.fcov.abund <- multifit( mod = "lm", multief = predictors, data = dec.mfit.fcov, formula = Abundance ~ multief, xlab = "scales", criterion = "R2")
Now we have something more interesting. Here we can see that both approaches identified the same scale of effect through the landscape analyzed. Nonetheless, we must highlight two important questions. At first, the shape of the R2 curves is quite different. Although both strategies detected X2000 as the peak of the R2 curve, we can clearly detect the decay after X2000 in the decoupled while in the nested strategy it seems to be more as a plato after X2000. Depending on the ecological question or study purpose, we may lose important information by considering only the nested approach.
As we just saw, it is quite a bit risky to get committed with a single strategy. While the nested approach has the advantage to almost never get a zero metrics (if it exists in the analyzed landscape) its nested nature make the responses equally smooth and may end on an overlook of some important features of the data. On the other hand, the decoupled strategy is quite sensitive to detect the scale of effect but might be deceivable to look at only this single approach since in nature things work together.
There are no silver bullets, but the decoupled approach can give us a level of detail that the nested approach usualy overlooks. We must always consider our objectives and questions and decide which one might be better. I encourage you to look at both as always as possible.
I hope you find this helpful.
Cheers.
Lázaro Carneiro, Milton C. Ribeiro, Willian M. Aguiar, Camila Priante, Wilson Frantine-Silva, Maria C. Gaglianone
Bee responses to landscape composition on coupled and decoupled multiscale approaches - Pre-print.
Lázaro Carneiro, Willian M. Aguiar, Camila Priante, Milton C. Ribeiro, Wilson Frantine-Silva, Maria C. Gaglianone
The Interplay Between Thematic Resolution, Forest Cover, and Heterogeneity for Explaining Euglossini Bees Community in an Agricultural Landscape. Front Eco Evol 2021
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.