[GIS] Split a single raster into multiple rasters based on the attributes in R

rrasterreclassify

I have a land cover raster which has 15 land cover classes (which previously had 70 land cover classes and I aggregated the same). However, I realized that I need 15 different rasters based on each of the land cover types. Is there any way I can achieve this in R?

lulc_2015 <- raster("E:\\LandCover_Data\\2015_lulc")

#Load matrix to be used for reclassification
rec <- read.csv("E:\\LandCover_ReclassifyMatrix.csv")

#Reclassifying the Raster to convert 70 LC to 15 LC
rc <- as.matrix(data.frame(from=rec$V2, to=rec$To))

New_LULC_2015 <- reclassify(lulc_2015,rc)

New_LULC_2015 <- ratify(New_LULC_2015)
rat <- data.frame(
  ID= 1:15,
  LandCover = c("Evergreen","Deciduous","Mixed Forest",
            "grass","Degraded Forest","Scrubland",
            "Dry Grassland","Wet Grassland","Plantation",
            "Settlement","High Elevation Plantation","Coastal",
            "Barren Land","Cropland","Wetlands")
  )

  levels(New_LULC_2015)<- rat

 > New_LULC_2015
 class       : RasterLayer 
 dimensions  : 642, 382, 245244  (nrow, ncol, ncell)
 resolution  : 1000, 1000  (x, y)
 extent      : 461951, 843951, 892583.3, 1534583  (xmin, xmax, ymin, ymax)
 coord. ref. : +proj=utm +zone=43 +datum=WGS84 +units=m +no_defs +ellps=WGS84 +towgs84=0,0,0 
 data source : in memory
 names       : layer 
 values      : 1, 15  (min, max)
 attributes  :
       ID LandCover
 from:  1 Evergreen
 to  : 15  Wetlands

If I try creating a new raster, I get this error.

> raster(New_LULC_2015@data@attributes[[1]]$ID==1)
 Error in (function (classes, fdef, mtable)  : 
  unable to find an inherited method for function ‘raster’ for signature 
 ‘"logical"’

I simply need 15 different rasters, for Evergreen, Deciduous etc. I need these as I realized I need to use the predict function from the raster package for a random forest model (Unless I don't really need to create separate rasters).

Best Answer

You can use mask() to create rasters by each class and assign() to assign class names to new rasters. A reproducible example:

library(raster)

set.seed(123)

New_LULC_2015 <- raster()

values(New_LULC_2015) <- sample(x = 1:15,size = ncell(New_LULC_2015),replace = T)

rat <- data.frame(
  ID= 1:15,
  LandCover = c("Evergreen","Deciduous","Mixed Forest",
                "grass","Degraded Forest","Scrubland",
                "Dry Grassland","Wet Grassland","Plantation",
                "Settlement","High Elevation Plantation","Coastal",
                "Barren Land","Cropland","Wetlands")
)

levels(New_LULC_2015)<- rat

ls() # to see which objects are created in the workspace
## [1] "New_LULC_2015" "rat" 

# create class names without space
rat$class_names <- gsub(pattern = ' ' ,replacement = '_',x = rat$LandCover)

There are two frequent methods to achieve this (as was exposed in comments). I like to use mask() because is faster:

library(microbenchmark)

test <- New_LULC_2015

microbenchmark(method_A=test[test != 1] <-NA,
               metohd_B=mask(test,test!=1, maskvalue=1))

## Unit: milliseconds
##      expr       min        lq     mean    median        uq      max neval cld
##  method_A 11.409580 11.743502 12.29027 12.136334 12.598599 17.27935   100   b
##  metohd_B  5.770045  6.502082  6.96712  6.612055  6.972143 11.85464   100  a 

remove(test)

Finally, create the new rasters based on the second method:

for(i in 1:15){
  assign(rat$class_names[i],mask(New_LULC_2015,New_LULC_2015 != i, maskvalue=1))
}

ls()
##  [1] "Barren_Land"               "Coastal"                   "Cropland"                 
##  [4] "Deciduous"                 "Degraded_Forest"           "Dry_Grassland"            
##  [7] "Evergreen"                 "grass"                     "High_Elevation_Plantation"
## [10] "i"                         "Mixed_Forest"              "New_LULC_2015"            
## [13] "Plantation"                "rat"                       "Scrubland"                
## [16] "Settlement"                "Wet_Grassland"             "Wetlands"    

Also, you can drop items to a list if you don't want to handle lot of objects in the workspace:

r_list <- list()

for(i in 1:15){
  r_list[[i]] <- mask(New_LULC_2015,New_LULC_2015 != i, maskvalue=1)
}