1

I have multiple raster .tif files. I'm using r and want to extract a cell's attribute value from all rasters based on an latitude and longitude input, and saved in a single .csv file. The output should be formatted as follows:

      Lat          Long       Value*       Value**
     20.15        77.12        12            20

*denotes attribute values from raster 1.
** denotes attribute values from raster 2.

Can anyone help me in this.

3

EDIT 2: I provide a shorter version based on extract function from the raster package.

library(raster)
library(sp) # used to create a SpatialPoint object

# LOAD RASTERS INTO A LIST OBJECT. 
tmp <- lapply(list.files("D:/rasters", pattern = ".tif$", full.names = TRUE), raster)

# A DATA FRAME WITH THE FOLLOWING STRUCTURE IS REQUIRED
coords <- data.frame("lat" = c(-2.2, -13.76, 4.47), "lon" = c(5.97, 10.57, 8.7))

# NEW CODE STARTS HERE
pts <- SpatialPoints(coords = coords, 
              proj4string = CRS("+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs "))

# THE NEXT LINE PROVIDES THE SAME OUTPUT AS THE FOLLOWING LONG CODE
as.data.frame(cbind(coords, do.call("rbind", lapply(tmp, extract, pts))))

I provide a generalized answer by making usage of a raster library functionality. It can be used to process multiple raster files and multiple lat-lon pairs.

The main idea is to use cellFromXY to get the cell index for a specific lat-lon pair. Then just extract the value using r[cellIndex], when r is a raster object.

This is given for a data frame with one row - i.e. only one pair of lat-lon, but you can easily wrap it with another lapply combined with rbind to iterate it over multiple lat-lon pairs.

EDIT: now you can run the code using multiple lat-lon points. Note that the input data.frame structure should be kept.

library(magrittr) # I used piping in my answer (%>%)
library(raster)   # raster functionality in r

# Assuming my .tif files are in this path: "D:/rasters"    

# LOAD RASTERS INTO A LIST OBJECT. 
tmp <- lapply(list.files("D:/rasters", pattern = ".tif$", full.names = TRUE), raster)

# A DATA FRAME WITH THE FOLLOWING STRUCTURE IS REQUIRED
coords <- data.frame("lat" = c(-2.2, -13.76, 4.47), "lon" = c(5.97, 10.57, 8.7))

# RUN THE FOLLOWING TO GET A MATRIX WITH VALUES
cellData <- lapply(tmp, function(r) {
  apply(coords, MARGIN = 1, FUN = function(row) {
    # as.matrix(coords[row, c("lat", "lon")]) # print(row)
    cellIndex <- cellFromXY(r, row) # gives cell Index for lat/lon pair
    r[cellIndex]
  })
}) %>% do.call("cbind", .)

# BIND MATRIX AS A DATA FRAME
output <- as.data.frame(cbind(coords, cellData))

Finally my result for 3 rasters and 3 points looks like this:

results

  • Hi, thanks. This is how I wanted the code to be - to choose multiple files together. But I am getting error while loading rasters into a list object. Could you help me writing that command properly..by writing proper path names etc. Thanks!! – Alexia k Boston Apr 11 '18 at 18:27
  • @Akb I have edited my answer. If it is useful you can vote it up / mark it as an answer. If you still get an error, please provide the error text in a comment/ question edit / new question – dof1985 Apr 12 '18 at 7:55
  • Thanks. The code ran successfully. In addition to this, could you tell me what if I have more than one lat and long. Can we process the same code in a way that we do not need to specify a particular lat and long value and it automatically reads all the lat long values from the grids of the raster. – Alexia k Boston Apr 12 '18 at 10:33
  • see edits for using several lat-lon pairs @Akb – dof1985 Apr 12 '18 at 12:13
  • 1
    @RionLerm, if you read the ?extract help in R, you'll see that it accepts spatial polygons along with a raster object. So basically, you could use the approach here with zones. Note that it would perform zonal statistics, so you must provide the function with a function for summarizing the values in each zones. – dof1985 Nov 25 '18 at 20:48
1

Here is how I would do it. This assumes that the 2 rasters have exactly the same number of pixels and exactly the same extent

library(raster)
r1<-raster("MyRasterName1.tiff")
r2<-raster("MyRasterName2.tiff")

# Get the extent of each raster
r1Extent<-extent(r1)
r2Extent<-extent(r2)

# Extract each pixel value for r1 into a dataframe
r1Extraction<-extract(r1,r1Extent, df=TRUE, cellnumbers=TRUE)
# create a data frame with the coordinates of each cell.
r1Coords<-as.data.frame(xyFromCell(r1,r1Extraction[,2]))
# bind the coordinates with the values of the cell
r1Final<-cbind(r1Coords,r1Extraction[,3])

# Extract each pixel value for r2 into a data frame
r2Extraction<-extract(r2, r2Extent, df=TRUE, cellnumbers=TRUE)

# bind the extraction to the r1Final data frame.
finalData<-cbind(r1Final, r2Extraction[,3]

# change the column names to what you want.
colnames(myFinalData)<-c("X","Y","R1","R2")

# Save as a CSV
write.csv(finalData, file="myFileName.csv", row.names = FALSE)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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