How to batch process geoTIFFs in R with lapply

ぃ、小莉子 提交于 2019-12-12 09:04:30

问题


I have some large geoTIFFs, now I want to convert them to ASCII files, after doing some searches, I write these codes:

library(raster)

f <- list.files("inputFolder", pattern = "*.tif", full.names = TRUE)
r <- lapply(f, raster)
a <- lapply(r, writeRaster, filename = "output", format = "ascii")

What confused me is that how can I name the output files respectively, according to its original names?

I tried:

a <- lapply(r, writeRaster, filename = "outputFolder" + f, format = "ascii")

But I received error:

non-numeric argument to binary operator

Then I tried:

a <- lapply(r, writeRaster, filename = paste0(f, ".asc"), format = "ascii")

But I received:

Error in file(filename, "w") : invalid 'description' argument In addition: Warning messages: 1: In if (filename == "") { : the condition has length > 1 and only the first element will be used 2: In if (!file.exists(dirname(filename))) { : the condition has length > 1 and only the first element will be used 3: In if (toupper(x@file@name) == toupper(filename)) { : the condition has length > 1 and only the first element will be used 4: In if (trim(filename) == "") { : the condition has length > 1 and only the first element will be used 5: In if (!file.exists(dirname(filename))) { : the condition has length > 1 and only the first element will be used 6: In if (filename == "") { : the condition has length > 1 and only the first element will be used 7: In if (!overwrite & file.exists(filename)) { : the condition has length > 1 and only the first element will be used


回答1:


I think you were basically nearly there, with two corrections:

First, you're calling writeRaster for its side effects (i.e. its ability to write a file to your filesystem) so you don't need to assign the output of your lapply() loop to an object. So, removing a <- we have:

lapply(r, writeRaster, filename = paste0(f, ".asc"), format = "ascii")

Next, the filename argument won't loop through f in this way. You have two options, of which the simplest is probably to pass the @file@name slot of r to the filename argument using an anonymous function:

lapply(r, function(x) {
  writeRaster(x, filename = x@file@name, format = "ascii", overwrite = TRUE)
})

Your other option would be to loop through r and f in parallel like you can in python with for r, f in..., which can be done with purrr:

library("purrr")
walk2(r, f, function(x, y) {
  writeRaster(x = x, filename = y, format = "ascii")
})

Here we're using walk2() rather than map2() because we need to call the function for side effects. This loops through r and f together so you can pass one to be the object to write, and one to be the filename.


Edit: here's the code I use to reproduce the problem

library("raster")

tmp_dir = tempdir()
tmp     = tempfile(tmpdir = tmp_dir, fileext = ".zip")

download.file(
  "http://biogeo.ucdavis.edu/data/climate/cmip5/10m/cc26bi50.zip",
  destfile = tmp
)
unzip(tmp, exdir = tmp_dir)

f = list.files(tmp_dir, pattern = ".tif$", full.names = TRUE)
r = lapply(f, raster)

# Solution one
lapply(r, function(x) {
  writeRaster(x, filename = x@file@name, format = "ascii", overwrite = TRUE)
})

# solution two
library("purrr")
walk2(r, f, function(x, y) {
  writeRaster(x = x, filename = y, format = "ascii")
})



回答2:


To test how to do this with small files:

library(raster)
s <- stack(system.file("external/rlogo.grd", package="raster")) 
writeRaster(s, file='testtif', format='GTiff', bylayer=T, overwrite=T)
f <- list.files(pattern="testtif_..tif")

Now you can use f with Phil's nice examples. You can also combine all in one step lapply:

f <- list.files("inputFolder", pattern = "*.tif", full.names = TRUE)
r <- lapply(f, function(i) { writeRaster(raster(i), filename=extension(i, '.asc'), overwrite=TRUE)} )

But if you have trouble with lapply, write a loop (it is fine!):

for (i in 1:length(f)) {
   r <- raster(f[i])
   ff <- extension(f[i], '.asc')
   writeRaster(r, ff)
}

Or like this

for (file in f) {
   r <- raster(file)
   ff <- extension(file, '.asc')
   writeRaster(r, ff)
}


来源:https://stackoverflow.com/questions/47591678/how-to-batch-process-geotiffs-in-r-with-lapply

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!