How to calculate landscape metrics for local landscapes?
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
In the last few weeks, I was asked a similar question several times – how to calculate landscape metrics for local landscapes? In other words, how to divide the categorical input map into a number of smaller areas, and next calculate selected landscape metrics for each of the areas. Those areas have many names, such as tiles, squares, or motifels. The main goal of this post is to show how to calculate landscape metrics using the landscapemetrics R package.
To reproduce the results on your own computer, install and attach the following packages:
library(landscapemetrics) # landscape metrics calculation library(raster) # spatial raster data reading and handling library(sf) # spatial vector data reading and handling library(dplyr) # data manipulation
Reading the data
The first step is to read the input data.
data("augusta_nlcd") my_raster = augusta_nlcd
In this example, we will use the augusta_nlcd
dataset build in the landscapemetrics package.
It is also possible to read any spatial raster file with the raster()
function, for example my_raster = raster("path_to_my_file.tif")
.
The input file, however, should fulfill two requirements: (1) contain only integer values that represent categories, and (2) be in a projected coordinate reference system.
You can check if your file meets the requirements using the check_landscape()
function, and learn more about coordinate reference systems in the Geocomputation with R book.
Our example data looks like that:
plot(my_raster)
Creating a grid
One of the ways to create borders of local landscapes is to use the st_make_grid()
function.
This function accepts the input raster as the first argument and derives the input area’s coordinates from it.
Next, we also need to provide a second argument, either cellsize
or n
:
cellsize
– vector of length 1 or 2 – the side length of each grid cell in map units (usually meters)n
– vector of length 1 or 2 – the number of grid cells in a row/column
my_grid_geom = st_make_grid(my_raster, cellsize = 1500) my_grid = st_sf(geom = my_grid_geom)
Next, we can overlay the newly created grid on top of our input raster:
plot(my_raster) plot(my_grid, add = TRUE)
Calculating a metric
The calculation of landscape metrics for each cell can be done with the sample_lsm()
function.
It requires the input raster as the first argument, and the grid as the second one1.
Next, we can specify which landscape metrics we want to calculate.
For example, we selected marginal entropy to be calculated on a landscape level.
The complete list of the implemented metrics can be obtained with the list_lsm()
function.
Let us know if you are missing some metrics.
my_metric = sample_lsm(my_raster, my_grid, level = "landscape", metric = "ent") my_metric ## # A tibble: 126 x 8 ## layer level class id metric value plot_id percentage_inside ## <int> <chr> <int> <int> <chr> <dbl> <int> <dbl> ## 1 1 landscape NA NA ent 2.54 1 100 ## 2 1 landscape NA NA ent 2.52 2 100 ## 3 1 landscape NA NA ent 2.47 3 100 ## 4 1 landscape NA NA ent 2.49 4 100 ## 5 1 landscape NA NA ent 2.38 5 100 ## 6 1 landscape NA NA ent 2.48 6 100 ## 7 1 landscape NA NA ent 2.65 7 100 ## 8 1 landscape NA NA ent 2.41 8 100 ## 9 1 landscape NA NA ent 2.28 9 100 ## 10 1 landscape NA NA ent 2.44 10 100 ## # … with 116 more rows
Each row in the my_metric
object corresponds to each provided grid cell, with the values of marginal entropy in the value
column
2.
Next, we can connect spatial grid with my_metric
using the bind_cols()
function:
my_grid = bind_cols(my_grid, my_metric)
The quickest visualization of the results can be done with the plot()
function.
plot(my_grid["value"])
More complex vizualizations can be done with the tmap or ggplot2 packages.
Saving the results
The write_sf()
function can save the results together with spatial geometry.
write_sf(my_grid, "my_grid.gpkg")
This output file can be read in any GIS software, such as QGIS, GRASS GIS, or ArcGIS.
Bonus 1 – show each raster
We can also see local landscapes for each grid cell, when we set the return_raster
argument in sample_lsm()
to TRUE
:
my_metric_r = sample_lsm(my_raster, my_grid, level = "landscape", metric = "ent", return_raster = TRUE) my_metric_r ## # A tibble: 126 x 9 ## layer level class id metric value plot_id percentage_insi… ## <int> <chr> <int> <int> <chr> <dbl> <int> <dbl> ## 1 1 land… NA NA ent 2.54 1 100 ## 2 1 land… NA NA ent 2.52 2 100 ## 3 1 land… NA NA ent 2.47 3 100 ## 4 1 land… NA NA ent 2.49 4 100 ## 5 1 land… NA NA ent 2.38 5 100 ## 6 1 land… NA NA ent 2.48 6 100 ## 7 1 land… NA NA ent 2.65 7 100 ## 8 1 land… NA NA ent 2.41 8 100 ## 9 1 land… NA NA ent 2.28 9 100 ## 10 1 land… NA NA ent 2.44 10 100 ## # … with 116 more rows, and 1 more variable: raster_sample_plots <list>
This adds a new column, raster_sample_plots
, that contains each local landscapes.
Next, we can vizualize whichever landscapes we want, for example, number 1
which is located in the bottom left corner of the study area:
plot(my_metric_r$raster_sample_plots[[1]], main = paste0("ent: ", round(my_metric_r$value[[1]], 2)))
Bonus 2 – calculate many metrics
We are not limited to calculating just one metric at the time.
The landscapemetrics package makes it possible to calculate up to 65 metrics on landscape level.
There are several ways to specify the metrics we want to obtain as you can learn in the ?calculate_lsm
help file.
For this example, we selected two metrics – marginal entropy (abbriviation "ent"
) and mutual information (abbriviate as "mutinf"
):
my_metrics = sample_lsm(my_raster, my_grid, level = "landscape", metric = c("ent", "mutinf")) my_metrics ## # A tibble: 252 x 8 ## layer level class id metric value plot_id percentage_inside ## <int> <chr> <int> <int> <chr> <dbl> <int> <dbl> ## 1 1 landscape NA NA ent 2.54 1 100 ## 2 1 landscape NA NA mutinf 1.07 1 100 ## 3 1 landscape NA NA ent 2.52 2 100 ## 4 1 landscape NA NA mutinf 0.841 2 100 ## 5 1 landscape NA NA ent 2.47 3 100 ## 6 1 landscape NA NA mutinf 0.973 3 100 ## 7 1 landscape NA NA ent 2.49 4 100 ## 8 1 landscape NA NA mutinf 1.09 4 100 ## 9 1 landscape NA NA ent 2.38 5 100 ## 10 1 landscape NA NA mutinf 1.04 5 100 ## # … with 242 more rows
The output data frame has two rows for each grid cell; therefore, if we want to connect the result with a spatial object, we need to reformat it.
It can be done with the pivot_wider()
function from the tidyr package.
library(tidyr) my_metrics = pivot_wider(my_metrics, names_from = metric, values_from = value) my_metrics ## # A tibble: 126 x 8 ## layer level class id plot_id percentage_inside ent mutinf ## <int> <chr> <int> <int> <int> <dbl> <dbl> <dbl> ## 1 1 landscape NA NA 1 100 2.54 1.07 ## 2 1 landscape NA NA 2 100 2.52 0.841 ## 3 1 landscape NA NA 3 100 2.47 0.973 ## 4 1 landscape NA NA 4 100 2.49 1.09 ## 5 1 landscape NA NA 5 100 2.38 1.04 ## 6 1 landscape NA NA 6 100 2.48 1.15 ## 7 1 landscape NA NA 7 100 2.65 1.12 ## 8 1 landscape NA NA 8 100 2.41 0.779 ## 9 1 landscape NA NA 9 100 2.28 0.914 ## 10 1 landscape NA NA 10 100 2.44 0.857 ## # … with 116 more rows
This function moves metrics values from the value
column into two new columns – ent
and mutinf
.
Now, we are able to connect it to the spatial object with bind_cols()
:
my_grid2 = bind_cols(my_grid, my_metrics)
Plotting of the result requires providing the name of the column of a metric:
plot(my_grid2["ent"])
plot(my_grid2["mutinf"])
Summary
The sample_lsm()
function offers more than calculations for regular areas.
It is also possible to provide irregular polygons as the second argument and calculate any landscape metrics for them.
The landscapemetrics package also has many additional features, including calculation of metrics in moving window with window_lsm()
and in subsequential buffers around points of interest with scale_sample()
.
Learn more about landscape metrics and the landscapemetrics package at https://r-spatialecology.github.io/landscapemetrics/ and http://dx.doi.org/10.1111/ecog.04617.
- This function also allows for many more possibilities, including specifying 2-column matrix with coordinates, SpatialPoints, SpatialLines, SpatialPolygons, sf points or sf polygons as the second argument. You can learn all of the possible options using
?sample_lsm
. [return] - To learn more about the structure of the output read the Efficient landscape metrics calculations for buffers around sampling points blog post. [return]
R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.