2

Is it possible to mask and/or crop a raster to multiple polygons, with the output being multiple raster's (i.e., a raster stack)?

Here's a reproducible example:

library(tidyverse)
library(raster)
library(sf)
filename <- system.file("external/test.grd", package="raster")
r <- raster(filename)

#  Create a data frame containing the centroids of a polygon 
(df <- data.frame(
  x = c(180000, 180500),
  y = c(331700, 332200)))

# create a point shapefile from the dataframe, then convert to polygon
polygon <- df %>%
  st_as_sf(coords = c("x", "y"), crs = crs(r)) %>%
  summarise(geometry = st_combine(geometry)) %>%
  st_cast("POINT") %>% 
  st_buffer(dist=200)

# plot the raster and polygon 
plot(r)
plot(polygon, add=TRUE)

enter image description here

# mask and crop the raster
        m <- r %>% mask(polygon) %>%
          crop(polygon)

The above code returns a single raster. How to return multiple rasters for each polygon?

3
  • 1
    Just nest the functions. As long as your polygons are all in a single object, you can just do something like: raster::mask( raster::crop(r, raster::extent(p)), p) Commented Jan 29, 2021 at 21:58
  • 1
    @JeffreyEvans If I understand it correctly, OP wants the output to be a different RasterLayer for each polygon feature. The nested code produces the same output as OP's reproducible example. Commented Jan 29, 2021 at 22:17
  • 1
    @Christopher, apologizes, you are correct. The OP wants separate rasters for each feature. Commented Jan 29, 2021 at 22:33

2 Answers 2

4

You can do this with an lapply function for the iterator, in leu of a for loop. The result is a list object containing the feature subset rasters.

library(sf)
library(raster)

r <- raster(system.file("external/test.grd", package="raster"))
p <- as(sf::st_buffer(as(sampleRandom(r, 4, sp=TRUE), "sf"), 200), "Spatial")

( rp <- lapply(1:nrow(p), function(x) 
          raster::mask(crop(r, extent(p[x,])), p[x,]) ) )

If you subset (crop) to the common polygon extent you can create a stack.

( rp <- do.call(stack,lapply(1:nrow(p), function(x) 
          raster::mask(crop(r, extent(p)), p[x,]) )) )
plot(rp)
3

I would just loop through your data frame and collect the outputs in a new brick. You can't crop the outputs if you want them to be in the same brick/stack because the extents of the outputs needs to be the same.

library(tidyverse)
library(raster)
library(sf)

filename <- system.file("external/test.grd", package="raster")
r <- raster(filename)

df <- data.frame(
  x = c(180000, 180500),
  y = c(331700, 332200))

#Make a copy of the input raster to collect the outputs
output <- brick(r)

for(i in 1:nrow(df)){
  polygon <- df[i,] %>%
    st_as_sf(coords = c("x", "y"), crs = crs(r)) %>%
    summarise(geometry = st_combine(geometry)) %>%
    st_cast("POINT") %>% 
    st_buffer(dist=200)
  
  #You can't crop here because the extents of the outputs need to be the same
  m <- r %>% mask(polygon)
 
  #Add the new raster to the output brick
  output <- addLayer(output, m)
   
}

#Drop the first layer, which is just in the input raster
output <- dropLayer(output, 1)

If you want the output rasters to be cropped to the individual polygons, you could collect the outputs in a list instead of a brick/stack.

I hope I understood your question correctly.

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.