如何找到像素标准偏差?

时间:2015-11-13 19:52:44

标签: r spatial raster

我有20个具有相同分辨率和范围的栅格。它是一个时间序列,每个栅格都是一年。

我想计算所有栅格的像素标准偏差。到目前为止,我正在使用光栅包。

qq2<-list(maxras1,maxras2,maxras3,maxras4,maxras5,maxras6,maxras7,maxras8,maxras9,maxras10)
qq2stack<-stack(qq2)
qq2mean<-mean(qq2stack)
qq2sd<-sd(qq2stack)

卑鄙的作品。但标准偏差给了我这个错误:

Error in as.double(x) : 
  cannot coerce type 'S4' to vector of type 'double'

2 个答案:

答案 0 :(得分:5)

不幸的是,正如您在上述评论后所述,每像素分析可能会很慢。我认为接下来要尝试的是并行化流程。假设您有一个多核处理器,您可以利用calc()及其内置的多进程优化:

cores <- 4
beginCluster(cores, type='SOCK')
calc(qq2stack, fun=sd)
endCluster()

如果您的操作/硬件环境支持,这将导致显着的加速。显然,您可以根据您的体系结构增加进程数。

答案 1 :(得分:5)

为了解决raster::calc用于计算大型栅格的标准偏差的缓慢性能,我写了一个要点(here),使用GDAL gdal_calc.py来完成它。

要计算5个具有4百万个单元格(2000 x 2000)的栅格的sd,gdal_calc大约需要2秒,而raster::calc大约需要60秒(参见下面的示例)。

您需要在系统路径上使用gdal_calc.py,以便Sys.which找到它,或者修改gdal_calc <- Sys.which('gdal_calc.py')以指定gdal_calc.py的完整路径。

请注意,从内存中,此函数最多支持26个输入栅格,因为gdal_calc每个都用字母表中的字母表示。也许这种约束可以被规避 - 我对gdalnumeric语法不够熟悉,无法解决这个问题。

E.g:

首先,让我们创建一个包含五个随机,2000 x 2000栅格的堆栈。我们将在此堆栈上使用raster::calc,但我们也会将它们写入临时文件,因为gdal_calc需要文件路径:

s <- stack(replicate(5, raster(matrix(runif(4000000), 2000))))  
ff <- replicate(5, tempfile(fileext='.tif')) # a vector of temp file paths
writeRaster(s, ff, bylayer=TRUE)

这是raster::calc版本:

system.time(sd_calc <- calc(s, sd))

##  user  system elapsed 
## 79.83    0.08   80.00

gdal_sd(即使用gdal_calc.py)版本:

devtools::source_gist('61c8062938e05a4c6b92') # source the gdal_sd gist
system.time(gdal_sd(infile=ff, outfile=f <- tempfile(fileext='.tif')))

## Calculating standard deviation and writing to file17b0146640ac.tif
##    user  system elapsed 
##    0.00    0.03    2.05 

比较他们的价值观:

range(sd_calc[] - raster(f)[])
## [1] -1.110223e-16  1.110223e-16

请注意,raster::calc对于小型栅格来说可能更快,但显然gdal_sd对于大型栅格来说是一个巨大的改进。

gdal_calc使用的标准差函数的文档给出here。我已经指定ddof=1(即delta自由度),结果与R sd返回的结果一致。

对于后人来说,这是gdal_sd的来源,就像发布时一样:

gdal_sd <- function(infile, outfile, quiet=TRUE) {
  require(rgdal)
  # infile:   The multiband raster file (or a vector of paths to multiple raster
  #           files) for which to calculate cell standard deviations.
  # outfile:  Path to raster output file.
  # quiet:    Logical. Should gdal_calc.py output be silenced?
  gdal_calc <- Sys.which('gdal_calc.py')
  if(gdal_calc=='') stop('gdal_calc.py not found on system.')
  if(file.exists(outfile)) stop('outfile already exists.')
  nbands <- sapply(infile, function(x) nrow(attr(GDALinfo(x), 'df')))
  if(length(infile) > 26 || nbands > 26) stop('Maximum number of inputs is 26.')
  if(length(nbands) > 1 & any(nbands > 1)) 
    warning('One or more rasters have multiple bands. First band used.')

  if(length(infile)==1) {
    inputs <- paste0('-', LETTERS[seq_len(nbands)], ' ', infile, ' --', 
           LETTERS[seq_len(nbands)], '_band ', seq_len(nbands), collapse=' ')
    n <- nbands
  } else {
    inputs <- paste0('-', LETTERS[seq_along(nbands)], ' ', infile, ' --', 
           LETTERS[seq_along(nbands)], '_band 1', collapse=' ')
    n <- length(infile)
  }

  message('Calculating standard deviation and writing to ', basename(outfile))
  cmd <- 'python %s %s --outfile=%s --calc="std([%s], 0, ddof=1)"'
  out <- system(
    sprintf(cmd, gdal_calc, inputs, outfile, 
            paste0(LETTERS[seq_len(n)], collapse=',')),
    show.output.on.console=!quiet, intern=TRUE
  )
  if(any(grepl('Error', out))) stop(out, call.=FALSE) else NULL
}