Themotif package implements ideas of thepattern-based spatial analysis in R. Its role is to describe spatialpatterns of categorical raster data for any defined regular andirregular areas. Patterns are represented quantitatively using built-insignatures based on co-occurrence matrices but also allows for anyuser-defined functions. It also enables spatial analysis such as search,change detection, and clustering to be performed on spatialpatterns.
Themotif package works on raster data representedbystars objects. It has several example datasets,including"raster/landcover2015.tif". This file contains aland cover data for New Guinea, with seven possible categories: (1)agriculture, (2) forest, (3) grassland, (5) settlement, (6) shrubland,(7) sparse vegetation, and (9) water.
library(motif)library(stars)#> Loading required package: abind#> Loading required package: sf#> Linking to GEOS 3.13.0, GDAL 3.10.3, PROJ 9.6.0; sf_use_s2() is TRUElibrary(sf)landcover=read_stars(system.file("raster/landcover2015.tif",package ="motif"))#> downsample set to 11We can see that most of the island is covered by forest, with someagriculture and smaller areas of the other classes. It is alsoreasonably easy to describe these proportions (so-called composition)numerically - we just need to count cells of each category for the wholedata.
We can use thelsp_signature() function for this. Itrequires astars object as the first input and the type ofa signature to calculate -"composition" in this case.There are also several additional arguments, includingthreshold - a share (between 0 and 1) of NA cells to allowsignature calculation andnormalization - decision if theoutput vector should be normalized.
landcover_comp=lsp_signature(landcover,type ="composition",threshold =1,normalization ="none")landcover_comp#> # A tibble: 1 × 3#> id na_prop signature#> * <int> <dbl> <list>#> 1 1 0.666 <int [1 × 7]>The output oflsp_signature(),landcover_comp, has a new classlsp. It is atibble with three columns:
id - an id of each window (area)na_prop - share (0-1) ofNA cells for eachwindowsignature - a list-column containing with calculatedsignaturesWe can take a look at the last column:
It is a list of signatures. In this case, we have just one signaturedescribing the whole area in the form of a numeric vector. It containshow many cells belong to each land cover category. For example, thereare 8122776 cells of forest, but only 2677 cells of shrubland.
Another approach would be to divide this large area into many regularrectangles (we refer to them as local landscapes) and to calculate asignature in each of them. The previously used signature,"composition" has one important flaw though. It onlydescribes how many cells of each category we have. However, it does notdistinguish an area with the left half of forest and right half ofagriculture from an area with forest mixed with agriculture (think of agreen-yellow checkerboard). Gladly, several more types of signatures doexist. It includes a co-occurrence matrix (type = "coma")."coma" goes to each cell, looks at its value, looks at thevalues of its neighbors and counts how many neighbors of each class ourcentral cell has.
#> downsample set to 11This time, we set thewindow argument to200, which means that each local landscape will consist of200 by 200 cells. In this example, each cell has a resolution of 300 by300 meters, therefore a local landscape will be 60000 by 60000 meters(60 by 60 kilometers).
landcover_coma=lsp_signature(landcover,type ="coma",window =200)landcover_coma#> # A tibble: 298 × 3#> id na_prop signature#> * <int> <dbl> <list>#> 1 2 0.644 <int [7 × 7]>#> 2 3 0.0992 <int [7 × 7]>#> 3 4 0.145 <int [7 × 7]>#> 4 5 0.602 <int [7 × 7]>#> 5 6 0.775 <int [7 × 7]>#> 6 9 0.796 <int [7 × 7]>#> 7 38 0.255 <int [7 × 7]>#> 8 39 0 <int [7 × 7]>#> 9 40 0 <int [7 × 7]>#> 10 41 0 <int [7 × 7]>#> # ℹ 288 more rowsNow, we have one row per local landscape, where each local landscapeis described by an id (id), the proportion of cells withNAs (na_prop), and a signature(signature). For example, the first signature looks likethis:
landcover_coma$signature[[1]]#> 1 2 3 4 5 6 7#> 1 16 24 0 0 0 0 12#> 2 24 53928 0 0 0 0 255#> 3 0 0 0 0 0 0 0#> 4 0 0 0 0 0 0 0#> 5 0 0 0 0 0 0 0#> 6 0 0 0 0 0 0 0#> 7 12 255 0 0 0 0 1644It is a matrix where each row and column represent subsequent landcover classes. For example, 141250 times forest cell is next to antherforest cell, and 226 times water cell is next to forest cell. You canlearn more about this signature athttps://jakubnowosad.com/comat/articles/coma.html.Additional signatures are described in theSpatialpatterns’ signatures vignette.
Themotif package also allows using irregularregions based on the user-provided polygons. It has an example spatialvector dataset,ecoregions.gpkg, which contains terrestrialecoregions for New Guinea fromhttps://ecoregions2017.appspot.com/.
This dataset has 22 rows, where each row relates to one ecoregion.Each ecoregion is also related to a unique value in theidcolumn.
Now, we need to provide this dataset and its identity column to thewindow argument oflsp_signature().
landcover_coma_e=lsp_signature(landcover,type ="coma",window = ecoregions["id"])landcover_coma_e#> # A tibble: 22 × 3#> id na_prop signature#> * <int> <dbl> <list>#> 1 1 0.114 <int [7 × 7]>#> 2 2 0.0851 <int [7 × 7]>#> 3 3 0.0377 <int [7 × 7]>#> 4 4 0.0914 <int [7 × 7]>#> 5 5 0 <int [7 × 7]>#> 6 6 0 <int [7 × 7]>#> 7 7 0.00285 <int [7 × 7]>#> 8 8 0.0720 <int [7 × 7]>#> 9 9 0.0508 <int [7 × 7]>#> 10 10 0 <int [7 × 7]>#> # ℹ 12 more rowsThe output,landcover_coma_e, is also of thelsp class and contains three columns. The first column,id, has the same values as provided in thewindow argument above. The third column,signature, has a spatial signature for each polygon in theecoregions dataset.
Themotif package also supports large rasterdatasets, including rasters that do not fit into the RAM. It justrequres reading the input data as astars.proxy by addingproxy = TRUE to theread_stars() function:
The rest of the calculations are the same as above.
Importantly, spatial patterns’ signatures can be used not only todescribe landscapes, but also to search for other similar landscapes,compare landscapes, and cluster them.
You can find examples of each of the above applications in thevignettes: