1

I am using Bivand's book to try an figure out how to use R for spatial data but struggling.

I have folder with annual tiff files for the years 1950 through 2010 (name: tas_mean_C_cru_TS31_01_1950, columns 4762, rows 2557, source type continuous, pixel type floating point, pixel depth 32 bit, compression LZW).

I want to clip them with a polygon layer and then put the clipped rasters in a new folder with the same name as the original raster. I have code below that I have tried to manipulate from examples in the book and online, but it does not work. My problem comes at the loop section and I get an error at the end.

My two questions are: 1) What is wrong with my loop statement? I am trying to loop through the files in the folder defined in input.path. 2) If I take a step back and ignore the clipping, how can I get the files to be copied and placed in a new folder with the same name?

Thanks Jen


#load libraries
library (sp)
library (rgdal)
library (raster)
library (maps)
library (mapproj)

#SET THE WORKING DIRECTORY PATH
input.path  = "F:/Dropbox/GIS/SNAP/Temp/tas50_09/"
#SET THE OUTPUT DIRECTORY
out.file<-"F:/temp/"
#FIND THE SIZE OF THE MATRIX -- WILL NEED THESE TO PRE-ALLOCATE SUBSEQUENT MATRICES
nrow <- 2557
ncol <- 4762
# initial rasters are....
# xmn=-2173225.11814296,xmx= 1498276.88185705, ymn = 409671.150470569, 
# ymx = 2381118.15047057, crs = '+proj=aea +lat_1=55 +lat_2=65 +lat_0=50 +lon_0=-154 +x_0=0 +y_0=0 +ellps=GRS80 +datum=NAD83 +units=m +no_defs')
# polygon to clip rasters
poly<-readOGR("F:/Dropbox/GIS/AKCommunities","AleutianComm50mile")
#reads the path to the files with a tif extention
file.names <- dir(input.path, pattern =".tif")
# then a loop for reading each existing file of type ".tif" as table
for(j in 1:length(input.path)){
  v <- extract(input.path, poly, weights=TRUE, cellnumbers=TRUE)
#Write the data to a geotiff
out <- raster(v ,xmn=-1446037.8545397,xmx= -686037.854539692, ymn = 356262.979377343, ymx = 607262.979377344, crs = '+proj=aea +lat_1=55 +lat_2=65 +lat_0=50 +lon_0=-154 +x_0=0 +y_0=0 +ellps=GRS80 +datum=NAD83 +units=m +no_defs')
writeRaster(v,filename=paste(out.file,'file.names ',sep=''),format = 'GTiff',options='COMPRESS=LZW',datatype='FLT4S',overwrite=T)
}
# I get the following error
Error in (function (classes, fdef, mtable)  : 
unable to find an inherited method for function ‘extract’ for signature ‘"character", "SpatialPolygonsDataFrame"’
Jen
  • 203
  • 1
  • 2
  • 12
  • 3
    Hi Jen, welcome to Stack Overflow. Questions that request suggestions for resources are considered off-topic here, and are typically closed quite quickly. You can bring your question in line with the site's rules by identifying a specific problem you're having with the code snippet you posted, rather than requesting opinions. – x4nd3r Nov 25 '14 at 04:05
  • Asking good questions is something of an art. It's not easy at first. There are very helpful [suggestions](http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example) on this topic. Though, to be fair, reproducible examples with spatial data can be tricky (that doesn't make it less important). If your question was more keyword focused, say "Iterate raster polygon clip?" more people with similar problems would have a chance at finding answers here. Thanks. – goangit Nov 26 '14 at 01:47
  • can't you stack all files and then clip the stacked file? – Paulo E. Cardoso Nov 27 '14 at 01:26

2 Answers2

1

The following edit may help you find problems in your logic.

Consistent naming schemes are a good thing when you need to iterate:

ipath <- "F:/Dropbox/GIS/SNAP/Temp/tas50_09/"
opath <- "F:/temp/"

ppath <- "F:/Dropbox/GIS/AKCommunities"
pname <- "AleutianComm50mile"

Avoid object names which may have namespace clashes, including "poly", "nrow" and "ncol".

ppoly <- readOGR(ppath,pname)

Be apprised, you don't use these values anywhere:

m <- 2557
n <- 4762

Pulling complicated literal values out of your loop improves readability:

p1 <- '+proj=aea +lat_1=55 +lat_2=65 +lat_0=50 +lon_0=-154'
p2 <- '+x_0=0 +y_0=0 +ellps=GRS80 +datum=NAD83 +units=m +no_defs'
projargs <- paste(p1,p2)

## output raster limits
xmn <- -1446037.8545397
xmx <- -686037.854539692
ymn <- 356262.979377343
ymx <- 607262.979377344

Use $ to anchor pattern match end-of-string and avoid unintentional mismatches.

files <- list.files(ipath, pattern='[.]tif$')
stopifnot(length(files)>0)

Now the problem area is much easier to read.

  1. Seems questionable whether you need weights and cellnumbers from extract().
  2. You may want to use nrow=m and ncol=n arguments in raster(), if v is not a matrix object:

Should be close now, anyway.

for (f in files) {

    ifile <- file.path(ipath,f)
    ofile <- file.path(opath,f)

    v  <- extract(ifile, ppoly, weights=TRUE, cellnumbers=TRUE)

    rv <- raster(v, crs=CRS(projargs), xmn=xmn, xmx=xmx, ymn=ymn, ymx=ymx)

    writeRaster(rv, filename = ofile, format='GTiff',
                options='COMPRESS=LZW', datatype='FLT4S', overwrite=TRUE)
}
goangit
  • 451
  • 4
  • 6
  • I did try that but the same error exists. This is the traceback... Error in (function (classes, fdef, mtable) : unable to find an inherited method for function ‘extract’ for signature ‘"character", "SpatialPolygonsDataFrame"’ 3 stop(gettextf("unable to find an inherited method for function %s for signature %s", sQuote(fdef@generic), sQuote(cnames)), domain = NA) 2 (function (classes, fdef, mtable) { methods <- .findInheritedMethods(classes, fdef, mtable) if (length(methods) == 1L) ... 1 extract(f, poly, weights = TRUE, cellnumbers = TRUE) – Jen Nov 25 '14 at 17:48
  • Closer inspection reveals a number of problems with your for() loop. For example, you are indexing using a variable j, which is never referred to in the body of the loop, j itself is the length of a string, rather than an iterable sequence of file names, and the call to writeRaster() passes an object which is not a raster. I think you are trying to do too much at once for your level of experience. I have edited the above to be logically consistent with what you seem to be aiming for, and more readable. – goangit Nov 26 '14 at 00:29
0

I realize this is almost two years old but I figured I can put my solution to whomever comes across this question. I'm ecstatic that I created my first for loop. I, too, had the same error messages. Using the naming convention of @goangit, I created something myself. Just slightly different. The convention is really organized, so I agree with @goangit and suggest this becomes a habit in the future. Its the shortest little thing. Anyway, below is the script for a generic raster clipping loop.

#Set your working directory
setwd("C:/Here_it_is/")
ipath <- "C:/Here_it_is/"   
#I know it repeats the above, but I noticed for me, it needed the wd set
opath <- "C:/Where_its_going/"

#Identify your polygon boundary
ppath <- "C:/GIS/" #directory where the .shp is 
pname <- "boundary" #filename of the actual .shp without the extension.

#Read your polygon boundary
ppoly <- readOGR(ppath,pname) #if this doesn't work theyn maybe you do not have the package loaded? 

#Identify spatial extent
e <- extent(ppoly)

#Projection type and datum, respectively
p1 <- "+proj=UTM"
p2 <- "+datum=WGS84"
projmap <- paste(p1,p2)

#Identify the list of images you wish to perform the loop
files <- list.files(ipath, pattern=".tif$", full.names=FALSE)
stopifnot(length(files)>0)

#add output directory
outfiles <- pasteO(opath, files) #paste0 forgoes any separator between the two vectors "opath" and "files". if you need to add a slash somewhere then you need to change it to the paste function or change your vectors above.

#Change extension
extension(outfiles) <- "tif" #if you want to make it .tif 

for (f in 1:length(files)){
r <- raster(files[f])
rc <- crop(r, e)
rm <- mask(rc, ppoly)
rw <- writeRaster(rm,outfiles[f],overwrite=TRUE)
}

#This should save where you designated the outfiles vector as.

MaeAntoinette
  • 183
  • 1
  • 1
  • 7
  • Thanks for the attempt. There are few typos in the code such as paste0 and rasater. There also is something going on with the readOGR line. It is a start and I can go from there. Thanks. – Jen Aug 23 '16 at 15:42
  • Hi Jen, Oops. Apologies for the typos. Consider the fact that I did not directly copy from my line of code and retyped within stackoverflow. Hopefully you can adjust the typos and it works out for you. Use "paste0" instead of pasteO. And of course, "rasater" is meant to be "raster". – MaeAntoinette Aug 24 '16 at 21:07