Function to Extract Elevation

Similar to the Planet workflow. In this test case, I downloaded 1/3 arc second DEMs from the USGS NED (in Maricopa), keep them in a folder, wrote a function in R to mosaic whatever is in that folder, then join to properties.

Prelims

#call packages
library(sf)
library(raster)
library(rgdal)
library(dplyr)
library(tmap)
library(tmaptools)

Example

Read in feature you want to join raster values to

MaricopaSample<- read_sf("MaricopaSample.shp")

As an example, consider a sample of Maricopa County properties (as points) and a single USGS 1/3 arc second DEM raster. We can clearly see that DEM tiles are smaller than the study area.

PointMap1<-#make map
  
    tm_shape(stack("USGS_13_n34w112_20210301.tif"), bbox= bb(MaricopaSample))+
    tm_raster(breaks = c(0, 200, 250, 300, 350, 400, 500, Inf))+
  
    tm_shape(MaricopaSample)+
    tm_dots( size=1 )+
    
    tm_layout(legend.show = FALSE)

PointMap1

There are actually 8 DEMs that intersect with Maricopa, two of which cover this sample. This makes joining elevation (or any raster information) to properties over a large area difficult.

PointMap2<-#make map
  
    tm_shape(stack("USGS_13_n34w112_20210301.tif"), bbox= bb(MaricopaSample))+
    tm_raster(breaks = c(0, 200, 250, 300, 350, 400, 500, Inf))+
  
    tm_shape(stack("USGS_13_n34w113_20130911.tif"), bbox= bb(MaricopaSample))+
    tm_raster(breaks = c(0, 200, 250, 300, 350, 400, 500, Inf))+
  
    tm_shape(MaricopaSample)+
    tm_dots(size=1)+
    
    tm_layout(legend.show = FALSE)

PointMap2

Join raster with user defined function

This function performs a join with many rasters by first mosaicing them together. The output is in the same format as the feature you join to (e.g. point, polygon).

# 2 inputs: the location of rasters to be mosaiced, and the shapefile (unit of analysis) you want to join raster values to 
RasterJoin<-function(RasterLocation,UOA){ 
 
  # make list of file names that are rasters. Note to change the pattern argument if rasters are not .tif. Alternatively you can remove the pattern argument if the file location only stores relevant raster files to be mosaiced. 
  current.list <- list.files(path=paste(RasterLocation), full.names=TRUE, pattern = ".tif") 
    
  # read in raster files as a raster stack
  raster.list<- lapply(current.list, stack) 
  
  # clear user defined names if present
  names(raster.list) <- NULL 
  
  # this tells the mosaic function to average any overlapping pixels
  raster.list$fun <- mean 
  
  # mosaic list using the mosaic function the raster package
  Mosaic <- do.call(mosaic, raster.list)
  
  # ensure joining units have a coordinate system
  UOA<-st_transform(UOA, crs = 3857)
  
  # match coordinate system of the mosaiced raster
  Mosaic<-projectRaster(Mosaic, crs = crs(UOA))

  # extract (join) raster values to points or polygons. 
  ex <- extract(Mosaic, 
    UOA, 
    fun=mean, #If polygons, take the mean raster values (change to sum or other function if desired)
    na.rm=TRUE,
    df=TRUE)

  ex <-cbind(UOA, ex)

return(ex)
}

Run RasterJoin Function

MaricopaElevation<-RasterJoin(RasterLocation= getwd(), #relative working directory, or change "getwd()" to raster folder
                                     UOA= MaricopaSample) # feature we want to join to

Export Features

st_write(MaricopaElevation,#export as shapefile
        paste(getwd(),"/","MaricopaElevation.shp",sep="")) #send to working directory (change to relevant folder and file name if different)

write.csv(MaricopaElevation, #export as csv
          paste(getwd(),"/","MaricopaElevation.csv",sep="")) #send to working directory (change to relevant folder and file name if different)

Map Example of the Joined Elevation

Note that the variable indicating elevation in the new data is “layer” which you can change to some appropriate heading

map3<-#make map
    tm_shape(MaricopaElevation)+
    tm_dots(col="layer", palette = "Reds", border.col = NULL, breaks = c(0, 200, 250, 300, 350, 400, 500, Inf), size = 1)

map3