提高性能/速度

时间:2012-03-29 16:17:12

标签: performance r loops raster

我需要从1303个栅格中获取数据(每个栅格有1个月的数据),并为栅格中的每个网格单元格创建一个时间序列。最后,我将把所有时间序列加入到一个大型(动物园)文件中。

我有能够做到这一点的代码(我尝试了一小部分数据集并且它有效)但它似乎只是为了堆叠栅格(现在超过2小时并仍在计数)不是较慢的部分,这将是时间序列。所以这是我的代码,如果有人知道更快的方式来堆叠栅格和/或创建时间序列(可能没有双循环?)请帮助......

我不知道任何其他编程语言,但这对R来说太多了吗?

files <- list.files(pattern=".asc") 
pat <- "^.*pet_([0-9]{1,})_([0-9]{1,}).asc$"
ord_files <- as.Date(gsub(pat, sprintf("%s-%s-01", "\\1", "\\2"), files))
files<-files[order(ord_files)]


#using "raster" package to import data 
s<- raster(files[1])
pet<-vector()
for (i in 2:length(files))
{
r<- raster(files[i])
s <- stack(s, r)
}

#creating a data vector
beginning = as.Date("1901-01-01")
full <- seq(beginning, by='1 month', length=length(files))
dat<-as.yearmon(full)

#building the time series
for (lat in 1:360)
for (long in 1:720)
{
pet<-as.vector(s[lat,long])
x <- xts(pet, dat)
write.zoo(x,file=paste("P:/WRSRL/Users1/ncgk/IBERIA/cru_pet/zoo/","lat",lat,"long",long,".csv", sep="")  , sep=",")
}

4 个答案:

答案 0 :(得分:2)

第一位可能只是:

s <- stack(files) 

创建堆栈有点慢的原因是需要打开每个文件并检查它是否与其他文件具有相同的nrow,ncol等。如果您绝对确定就是这种情况,您可以使用这样的快捷方式(通常不推荐)

quickStack <- function(f) {
r <- raster(f[1])
ln <- extension(basename(f), '')
s <- stack(r)
s@layers <- sapply(1:length(f), function(x){ r@file@name = f[x]; r@layernames=ln[x]; r@data@haveminmax=FALSE ; r })
s@layernames <- ln
s
}

quickStack(files)

您可以加速第二部分,如下面的示例所示,具体取决于您拥有多少RAM。

逐行阅读:

for (lat in 1:360) {
pet <- getValues(s, lat, 1)
for (long in 1:720) {
    x <- xts(pet[long,], dat)
    write.zoo(x,file=paste("P:/WRSRL/Users1/ncgk/IBERIA/cru_pet/zoo/","lat",lat,"long",long,".csv", sep="")  , sep=",")
}
}

更极端,一次读取所有值:

 pet <- getValues(s)
 for (lat in 1:360) {
for (long in 1:720) {
    cell <- (lat-1) * 720 + long
    x <- xts(pet[cell,], dat)
    write.zoo(x,file=paste("P:/WRSRL/Users1/ncgk/IBERIA/cru_pet/zoo/","lat",lat,"long",long,".csv", sep="")  , sep=",")
}
}

答案 1 :(得分:1)

我会在此重新发表评论并提供一个更好的例子:

一般思路:在执行'raster'循环之前为s分配空间。如果将s和r连接到循环内的新对象,则R必须为每次迭代为s分配新内存。这真的很慢,特别是如果s很大。

s <- c()
system.time(for(i in 1:1000){ s <- c(s, rnorm(100))})
# user  system elapsed 
# 0.584   0.244   0.885 

s <- rep(NA, 1000*100)
system.time(for(i in seq(1,1000*100,100)){ s[i:(i+99)] <- rnorm(100) })
# user  system elapsed 
# 0.052   0.000   0.050

如您所见,预分配的速度提高了大约10倍。

很遗憾,我不熟悉rasterstack,因此我无法告诉您如何将其应用于您的代码。

答案 2 :(得分:1)

这样的事情应该有效(如果你有足够的记忆):

#using "raster" package to import data 
rlist <- lapply(files, raster)
s <- do.call(stack, rlist)
rlist <- NULL # to allow freeing of memory

将所有raster个对象加载到一个大列表中,然后调用stack一次。

以下是速度增益的示例:对于60个文件,速度增加为1.25秒对8秒 - 但是您的旧代码在时间上是二次的,因此对于更多文件,增益会更高......

library(raster)
f <- system.file("external/test.grd", package="raster")
files <- rep(f, 60)

system.time({
 rlist <- lapply(files, raster)
 s <- do.call(stack, rlist)
 rlist <- NULL # to allow freeing of memory
}) # 1.25 secs

system.time({
 s<- raster(files[1])
 for (i in 2:length(files)) {
  r<- raster(files[i])
  s <- stack(s, r)
 }
}) # 8 secs

答案 3 :(得分:0)

我尝试了另一种处理大量文件的方法。 首先,我将时间序列栅格组合成一个NetCDF格式的文件, 使用write.Raster(x,format =“CDF”,..) 然后每年只读一个文件,这次我用砖(netcdffile,varname ='')它的读数节省了很多。 但是,我需要根据一些预定义的格式保存每个单元格的值,其中我使用write.fwf(x = v,...,append = TRUE) 但是需要很长时间才能获得近500,000分。 有没有人有同样的经验和帮助,如何加快这个过程? 这是我提取每个点的所有值的代码:

weather4Point <- function(startyear,endyear)  
{

  for (year in startyear:endyear)
  {
    #get the combined netCDF file

    tminfile <- paste("tmin","_",year,".nc",sep='')

    b_tmin <- brick(tminfile,varname='tmin')

    pptfile <- paste("ppt","_",year,".nc",sep='')

    b_ppt <- brick(pptfile,varname='ppt')

    tmaxfile <- paste("tmax","_",year,".nc",sep='')

    b_tmax <- brick(tmaxfile,varname='tmax')

    #Get the first year here!!!

    print(paste("processing year :",year,sep=''))

    for(l in 1:length(pl))
    {
      v <- NULL

      #generate file with the name convention with t_n(latitude)w(longitude).txt, 5 digits after point should be work

      filename <- paste("c:/PRISM/MD/N",round(coordinates(pl[l,])[2],5),"W",abs(round(coordinates(pl[l,])[1],5)),".wth",sep='')  

      print(paste("processing file :",filename,sep=''))            

      tmin <- as.numeric(round(extract(b_tmin,coordinates(pl[l,])),digits=1))

      tmax <- as.numeric(round(extract(b_tmax,coordinates(pl[l,])),digits=1))

      ppt <- as.numeric(round(extract(b_ppt,coordinates(pl[l,])),digits=2))

      v <- cbind(tmax,tmin,ppt)

      tablename <- c("tmin","tmax","ppt")

      v <- data.frame(v)   

      colnames(v) <- tablename

      v["default"] <- 0

      v["year"] <- year

      date <- seq(as.Date(paste(year,"/1/1",sep='')),as.Date(paste(year,"/12/31",sep='')),"days")

      month <- as.numeric(substr(date,6,7))

      day   <- as.numeric(substr(date,9,10))

      v["month"] <- month 

      v["day"]  <-  day

      v <- v[c("year","month","day","default","tmin","tmax","ppt")]

      #write into a file with format
      write.fwf(x=v,filename,append=TRUE,na="NA",rownames=FALSE,colnames=FALSE,width=c(6,3,3,5,5,5,6))
    }
  }
}
相关问题