2. Summarizing categorical data

Introduction

This vignette builds upon the sample data for São Miguel (introduced in the previous vignette) to demonstrate the use of exactextractr with categorical land cover data. A sample of the CORINE 2018 raster dataset is included in exactextractr.

As in the previous vignette, the following packages are used:

library(exactextractr)
library(dplyr)
library(sf)
library(raster)

Loading the sample data

First, we load the CORINE land cover data and the concelho boundaries.

clc <- raster(system.file('sao_miguel/clc2018_v2020_20u1.tif',
                     package = 'exactextractr'))
concelhos <- st_read(system.file('sao_miguel/concelhos.gpkg',
                                 package = 'exactextractr'),
                     quiet = TRUE)

The land cover class descriptions are provided in a separate DBF file. We read this in to a data frame, then use levels() to associate the class descriptions with the raster.

clc_classes <- foreign::read.dbf(system.file('sao_miguel/clc2018_v2020_20u1.tif.vat.dbf',
                                             package = 'exactextractr'),
                                 as.is = TRUE) %>%
  dplyr::select(value = Value,
                landcov = LABEL3)

levels(clc) <- list(data.frame(ID = clc_classes$value,
                               landcov = clc_classes$landcov))

This association provides us with a way to look up the description for a given ID. Alternatively, we can relate the values using merge or a `dplyr join.

factorValues(clc, c(2, 18, 24))
#>                      landcov
#> 1 Discontinuous urban fabric
#> 2                   Pastures
#> 3          Coniferous forest

Summarizing land cover classifications

One of the most basic questions we might ask is which land cover classification is predominant in each concelho. We can do this with the built-in mode summary operation. The minority and variety operations are also applicable to categorical data and provide the least-common classification and number of distinct classifications, respectively.

landcov_mode <- exact_extract(clc, concelhos, 'mode', 
                              append_cols = 'name', progress = FALSE) %>%
  inner_join(clc_classes, by=c(mode = 'value'))
name landcov
Lagoa Land principally occupied by agriculture, with significant areas of natural vegetation
Nordeste Coniferous forest
Ponta Delgada Pastures
Povoação Broad-leaved forest
Ribeira Grande Land principally occupied by agriculture, with significant areas of natural vegetation
Vila Franca do Campo Land principally occupied by agriculture, with significant areas of natural vegetation

Summary functions

While mode provides a handy way to see the most common land cover category, we need to write a custom summary function if we want to see the frequency of different land cover types in an area.

Summary functions are called once per feature from the input sf object. They can return either:

If we are going to perform typical data frame operations on the raster values and coverage fractions, it can be more convenient for the summary function to accept a single data frame argument, instead of separate arguments for the cell values and coverage fractions. This behavior can be enabled with the summarize_df argument.

Using this method, we can calculate the fraction of each concelho that is covered by each land cover category:

landcov_fracs <- exact_extract(clc, concelhos, function(df) {
  df %>%
    mutate(frac_total = coverage_fraction / sum(coverage_fraction)) %>%
    group_by(name, value)