Search code examples
rrasterspatialr-sf

Convert a line shapefile to a raster layer and preserve values


I have an sf object that contains road geoms and road types (e.g. secondary, highway, cycleway, etc.):

(code taken from this blog post)

library(osmdata)
library(tidyverse)

muenster <- 
  opq(bbox =  c(7.61, 51.954, 7.636, 51.968)) %>% 
  add_osm_feature(key = 'highway') %>% 
  osmdata_sf() %>% 
  osm_poly2line()

muenster_center <- muenster$osm_lines %>% 
  dplyr::select(highway)

I want to convert this shapefile to a raster file where the road types are preserved so that I can calculate cost paths.


Solution

  • NOTE Use terra which is the replacement for the raster package and it will be much faster and you won't need stars. See Robert's answer

    As you may have noticed rasterize is quite slow for large data sets. I created a function that wraps around stars::st_rasterize so that it takes a RasterLayer and sf and returns a RasterLayer

    rasterizeLine <- function(sfLine, rast, value){
      # rasterize roads to template
      tmplt <- stars::st_as_stars(sf::st_bbox(rast), nx = raster::ncol(rast),
                                  ny = raster::nrow(rast), values = value)
      
      rastLine <- stars::st_rasterize(sfLine,
                                      template = tmplt,
                                      options = "ALL_TOUCHED=TRUE") %>%
        as("Raster")
      
      return(rastLine)
    }
    
    library(osmdata)
    library(tidyverse)
    library(sf)
    
    muenster <- 
      opq(bbox =  c(7.61, 51.954, 7.636, 51.968)) %>% 
      add_osm_feature(key = 'highway') %>% 
      osmdata_sf() %>% 
      osm_poly2line()
    
    muenster_center <- muenster$osm_lines %>% 
      select(highway) %>% 
      # Note you have to turn it into a factor for stars to use that column and it
      # has to be the first column
      mutate(highway = as.factor(highway))
    
    r <- raster::raster(muenster_center, ncol=1000, nrow=1000)
    
    system.time({
      muenster_rast <- rasterizeLine(muenster_center, r, NA)
    })
    #   user  system elapsed 
    #   0.09    0.07    0.15 
    
    system.time({
      muenster_rast2 <- raster::rasterize(muenster_center, r, "highway")
    })
    #   user  system elapsed 
    # 207.56    0.06  208.75
    
    raster::freq(muenster_rast - muenster_rast2)
    #      value  count
    # [1,]    -2      1
    # [2,]     0  63676
    # [3,]    NA 936323
    

    Output looks very similar between the two but the version that uses stars is much faster!