Performance 提高性能/速度

Performance 提高性能/速度,performance,r,loops,raster,Performance,R,Loops,Raster,我需要从1303个光栅中获取数据,每个光栅有1个月的数据,并为光栅中的每个网格单元创建时间序列。最后,我将把所有的时间序列合并成一个庞大的动物园文件 我有代码可以做到这一点,我尝试了数据集的一小部分,它工作了,但似乎永远只需要堆叠光栅超过2小时,现在仍然计数,这不是较慢的部分,这将是做时间序列。这是我的代码,如果有人知道一种更快的方法来堆叠光栅和/或创建时间序列,也许没有双循环?请帮忙 我不知道任何其他编程语言,但这是不是太多的要求从R files <- list.files(patter

我需要从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=",")
}

我将在这里转载我的评论,并给出一个更好的例子:

总体思路是:在执行“光栅”循环之前为s分配空间。如果将s和r连接到循环中的新对象s,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倍


不幸的是,我不熟悉光栅和堆栈,因此无法告诉您如何将其应用于代码。

我将在此处重新发布我的评论,并给出一个更好的示例:

总体思路是:在执行“光栅”循环之前为s分配空间。如果将s和r连接到循环中的新对象s,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倍


不幸的是,我不熟悉光栅和堆栈,因此我无法告诉您如何将其应用于代码。

如果您有足够的内存,类似的方法应该可以工作:

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

如果您有足够的内存,这种方法应该可以工作:

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

第一位可以是:

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=",")
}
}

第一位可以是:

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=",")
}
}

我尝试了另一种处理大量文件的方法。 首先,我将时间序列光栅合并到一个NetCDF格式的文件中, 使用write.Rasterx,format=CDF,。。 然后每年只读取一个文件,这次我使用了bricknetcdffile,varname=it,读取节省了很多。 但是,我需要根据一些预定义的格式保存所有年份的每个单元格的值,其中我使用write.fwfx=v,…,append=TRUE 但这需要很长时间才能获得近50万分。 是否有人在如何加快这一进程方面有相同的经验和帮助? 以下是我提取每个点的所有值的代码:

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))
    }
  }
}

我尝试了另一种处理大量文件的方法。 首先,我将时间序列光栅合并到一个NetCDF格式的文件中, 使用write.Rasterx,format=CDF,。。 然后每年只读取一个文件,这次我使用了bricknetcdffile,varname=it,读取节省了很多。 但是,我需要根据一些预定义的格式保存所有年份的每个单元格的值,其中我使用write.fwfx=v,…,append=TRUE 但这需要很长时间才能获得近50万分。 是否有人在如何加快这一进程方面有相同的经验和帮助? 以下是我提取每个点的所有值的代码:

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))
    }
  }
}

问题是,代码的哪一部分需要多少时间。最后一个双循环将执行360*720次,这太多了。如果你有一个以上的CPU,你可以并行运行看看foreach。我仍然在努力导入所有文件,我认为光栅包将是最好的选择后,阅读了几篇文章在这里,但我不确定它是否适用于1303个文件。但read.table更糟糕!那么问题可能是这样的:对于每个迭代,R需要分配一个新的对象S,并且其大小不断增加。这种分配可能会花费很多时间。在循环之前分配s可能会更快。我给你举一个简单的例子:你的方式:s=c;对于1:10{s,问题是,代码的哪一部分需要多少时间。最后的双循环将执行360*720次,这是很多次。如果你有多个CPU,你可以并行运行,看看foreach。我是sti
在阅读了一些文章之后,我认为光栅包是最好的选择,但是我不确定它是否适用于1303个文件。但read.table更糟糕!那么问题可能是这样的:对于每个迭代,R需要分配一个新的对象S,并且其大小不断增加。这种分配可能会花费很多时间。在循环之前分配s可能会更快。我给你举一个简单的例子:你的方式:s=c;因为我在1:10{s谢谢,我试图通过在循环之前分配空间来做到这一点:files1文件的大小是多少?如果它们更大,20个文件8秒也不错。如果您使用colClasses参数指定数据类型,您可以加快read.table的速度。您是对的,我不知道光栅循环为什么现在运行了3个多小时…我会我杀了它,试着使用旧的read.table…谢谢,我试着通过在循环之前分配空间来做到这一点:files1文件的大小是多少?如果它们更大,20个文件的8秒也不错。如果你使用colClasses参数指定数据类型,你可以加快read.table的速度。你是对的,我不知道光栅循环为什么会这样我已经跑了3个多小时了…我会杀了它,然后试试那张好的老桌子…啊