我有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'
答案 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
}