所以,我有一些来自.nc文件的4D数组中的变量(x,y,z,t)。问题是,z坐标不是像x和y坐标那样均匀间隔,即z类似于25米,75米,125,175,......,500,600,700,...,20000, 21000,22000。我试图对数据进行线性插值以在整个z中获得均匀的50m间距。但是R中的近似函数运行得太慢(我认为数组太大了):
library(ncdf)
x = get.var.ncdf(nc,'x'); y = get.var.ncdf(nc,'y'); z = get.var.ncdf(nc,'z')
t = get.var.ncdf(nc,'t') # time
qc1 = get.var.ncdf(nc,'qc',start=c(1,1,1,1),count=c(-1,-1,-1,-1))
zlin = seq(z[1],z[length(z)],50)
qc1_lin = array(0,c(length(x),length(y),length(zlin),length(t)))
for (i in 1:length(x)) {
for (j in 1:length(y)) {
for (k in 1:length(t)) {
qc1_lin[i,j,,k] = approx(z,qc1[i,j,,k],xout = zlin)
}
}
}
有没有办法更快地完成这项工作?或者,有人告诉我调查数据以使这更容易,但我不太确定他的意思。有人能帮我吗?感谢。
答案 0 :(得分:1)
由于我没有你的ncdf文件,我以NOAA气温数据集为例:
library(ncdf)
url <- paste("ftp://ftp.cdc.noaa.gov/Datasets/ncep/air.",format(Sys.Date(),"%Y"),".nc",sep="")
download.file(url,destfile="air.nc")
nc <- open.ncdf("air.nc")
x <- get.var.ncdf(nc,'lon')
y <- get.var.ncdf(nc,'lat')
z <- get.var.ncdf(nc,'level')
t <- get.var.ncdf(nc,'time')
qc1 <- get.var.ncdf(nc,'air')
这里z
的值范围从1000到50,举一个简短的例子,让我们采用每100个级别间隔的常规网格(我还将限制数据集的前20天的操作以保持例如相对较小):
zlin <- seq(z[1],z[length(z)],-100)
使用您的方法:
qc1_lin <- array(0,dim=c(144,73,10,20))
system.time({
for (i in 1:length(x)) {
for (j in 1:length(y)) {
for (k in 1:20) {
# Don't forget that approx outputs a list
qc1_lin[i,j,,k] = approx(z,qc1[i,j,,k],xout = zlin)$y
}
}
}
})
user system elapsed
26.793 1.196 27.886
但您可以使用apply
执行相同的操作:参数MARGIN
也可以使用值向量。在这里,我们要在尺寸1,2和4上应用approx
函数(因为它是我们正在修改的第三个维度):
system.time({
qc1_lin2 <- apply(qc1[,,,1:20],c(1,2,4),function(X)approx(z,X,xout=zlin)$y)
})
user system elapsed
24.413 0.144 24.408
遗憾的是, apply
将新维度输出为第一维,因此我们需要对结果进行排列:
qc1_lin3 <- aperm(qc1_lin2, perm=c(2,3,1,4))
让我们检查一下结果是否相同:
all(qc1_lin3==qc1_lin)
[1] TRUE
时间收益相对较小但可能值得。
答案 1 :(得分:1)
这不是R中的答案,只是说可以使用CDO从命令行快速完成此任务
cdo intlevel,`seq -s "," 50 50 22000` in.nc out.nc
seq命令以50m的间隔生成一个从50到22000的逗号分隔列表。