你会如何加快这段代码的速度?降低netcdf中数据的分辨率,然后将其转换为xyz格式的统计数据

时间:2013-04-03 08:55:36

标签: r optimization geospatial netcdf rworldmap

我正在研究玉米产量和收获面积的netcdf,将分辨率从2.5弧分缩小到.5度,然后将整个事物转换为XYZ格式,这样我就可以更容易地与数据“对话”我已经采用这种格式了。 (我想我可以把我的其他数据变成矩阵形式,但我喜欢xyz。)

数据为here

下面的代码定义了一些函数来计算从收获面积和平均收益率的总产量,然后它在查询netcdf时使用一些“馈线”数据,然后它使用plyr循环通过馈线,提取数据,应用函数,然后保存在xyz中。它可以工作,但只运行其中一个文件大约需要30分钟,而且我已经超过100个。任何有关优化此代码的方法的建议都会很棒。提取更大的数据块并将功能应用于它们会更​​快吗?就像,也许是地球的整个条纹?我怎么知道先验是否会更快?

rm(list=ls()) 
library(ncdf)
library(reshape)
library(plyr)
library(sp)
library(maps)
library(rgeos)
library(maptools)
library(rworldmap)

getha = function(lat,size=lat[1]-lat[2]){
    lat1 = (lat-size/2)*pi/180
    lat2 = (lat+size/2)*pi/180
    lon1 = (0-size/2)*pi/180    #lon doesn't come in because all longitudes are great circles
    lon2 = (0+size/2)*pi/180
    6371^2 * abs(sin(lat1)-sin(lat2))*abs(lon1-lon2)*100    #6371 is the radius of the earth and 100 is the number of ha in a km^2
    }

gethamat = function(mat,latvec,blocksize=6){
    a = getha(latvec)
    areamat = matrix(rep(a,blocksize),blocksize)
    area = t(mat)*areamat   #The matrix is transposed because the dimensions of the Ramankutty's netcdf's are switched
    area
    }

getprod = function(yieldblock,areablock,latvec){
    b = gethamat(areablock,latvec)
    sum(t(yieldblock)*b,na.rm=TRUE)
    }

lat = as.matrix(seq(from=89.75,to=-89.75,by=-.5))
lon = as.matrix(seq(from=-179.75,to=179.75,by=.5))

lon = seq.int(from=1,to=4320,by=6)
lat = seq.int(from=1,to=2160,by=6)

lat = rep(lat,720)
lon = t(matrix(lon,720,360))
lon = as.data.frame(lon)
l = reshape(lon,direction="long",varying=list(colnames(lon)),v.names = "V")
coords = data.frame(cbind(l[,2],lat))
colnames(coords) = c("lng","lat")
feeder = coords
head(feeder)

maize.nc = open.ncdf('maize_5min.nc')

getcrops = function(feed,netcdf,var="cropdata"){
    yieldblock = get.var.ncdf(netcdf,varid=var,start = c(as.numeric(feed[1]),as.numeric(feed[2]),2,1),count = c(6,6,1,1))
    areablock = get.var.ncdf(netcdf,varid=var,start = c(as.numeric(feed[1]),as.numeric(feed[2]),1,1),count = c(6,6,1,1))
    lat = get.var.ncdf(netcdf,varid="latitude",start = feed[2],count = 6)
    prod = getprod(yieldblock,areablock,lat)
    lon = get.var.ncdf(netcdf,varid="longitude",start = feed[1],count = 6)
    #print(c(mean(lat),mean(lon)))
    data.frame(lat=mean(lat),lon = mean(lon),prod=prod)
    }

out = adply(as.matrix(feeder),1,getcrops,netcdf=maize.nc,.parallel=FALSE)

提前致谢。

1 个答案:

答案 0 :(得分:2)

当块的数量变大时,

plyr函数非常慢。我真的建议将数据保存在多维数组中。这允许您使用apply来例如得到所有lat-lon组合等的均值。多维数组占用较少的RAM存储空间,因为元数据不是直接存储为列,而是隐含在数组的维度内。此外,apply通常比使用plyr快得多。 ncdf包本身将数据读入多维数组,因此这也为您节省了处理步骤(例如使用melt)。

在缩小数据集之后,我经常会使用melt转到您所谓的XYZ格式进行绘图。但到那时,数据集非常小,以至于这并不是真的很重要。