2016-06-23 8 views
2

NCDef(.nc)形式の複数のファイルからデータを抽出しようとしています。私が書いたコードは、しかし、ゆっくりと、私は任意の提案に感謝したい!Slow for loop in R

私の作業コードは、tempというファイルをRNetCDFを使用してプルし、各変数が1次元または3次元(lat、lon、およびpft)のいずれかを持つ「長いリスト」に変換します。私は一度に一つ一つの変数からそれぞれのデータを引っ張って(varlist[j])、それをデータフレームに変換します。次に、3つの次元のそれぞれによってこれを分割する。最後のステップは、filesを作成することで、私はcbindとrbindを使ってすべてのファイルを1つの大きなデータフレームにまとめることができます。次のように

コードは次のとおり

setwd("C:/Users/User/Box Sync/_PhD/PhD_Research/Albedo/Data_CLM/PFTRuns/2005/") 
fname<-"b40.20th.1deg.bdrd.002bc.clm2.h0.2005-" 
numlist<-c('01','02','03','04','05','06','07','08','09','10','11','12') 
varlist<-c(1,2,4,8,9,21) 
varname<-c("lon","lat","pft","pft_wtgcell","pft_wtcol","FSR") 
files<-matrix(data=NA, nrow=12, ncol=length(varlist)) 

`for (i in 12:12) { 
    temp<- paste(c(fname, numlist[i],'.nc'), collapse='') 
    temp<-read.nc(open.nc(temp)) 
    temp<-structure(temp, row.names = c(NA, -288), class = "data.frame") 
    for (j in 3:length(varlist)) { 
    newname<-paste(c("Y2005", numlist[i],".", varname[j]), collapse='') 
    if (j<4){ 
     assign(newname, adply(temp[,varlist[j]], c(1)))} 
    else{ 
     assign(newname, adply(temp[,varlist[j]], c(1,2,3)))} 
    files[i,j]<-newname}}` 

はEDIT ここread.nc(open.nc())出力の例です。 Example Output

+1

で、上の和解答えです。 'read.nc(open.nc(temp)'の出力のサンプルを投稿すると、データフレームへの複数の変換を避け、最後にその操作を行うことでパフォーマンスが向上する可能性があります。 dplyrが別のパフォーマンスを向上させる可能性があります。 – Dave2e

+0

この出力を追加し、さらにコードを表示しました。 –

+0

ループは問題ではなく、リアルタイムで消費するステップであるplyrの 'adply'ステートメントですおそらく他の人が代用関数やRcppコードを提案してパフォーマンスを改善するかもしれません。 – Dave2e

答えて

0

問題を確認します。一連の3次元配列を1次元配列に平坦化し、座標ベクトル(lon、lat、put)と整列させたいと思います。
パッケージplyrには多くの非常に便利な機能がありますが、遅くなる傾向があります。上記のあなたの場合と同じです。

ここで私はテストのために作成したサンプルデータ:

#create some test data 
set.seed(1) 
lon<-1:300 
lat<-1:200 
pft<-1:15 
tot<-length(lon)*length(lat)*length(pft) 
pft_wtgcell<- array(rnorm(tot, 10), dim=c(length(lon),length(lat),length(pft))) 
pft_wtcol<- array(rnorm(tot, 60, 2), dim=c(length(lon),length(lat),length(pft))) 
FSR<- array(rnorm(tot, 100, 3), dim=c(length(lon),length(lat),length(pft))) 
temp<-list(lon=lon, lat=lat, pft=pft, pft_wtgcell=pft_wtgcell, pft_wtcol=pft_wtcol, FSR=FSR) 

ここでは私のソリューションです:

numlist<-c('01','02','03','04','05','06','07','08','09','10','11','12') 
#varlist<-c(1,2,4,8,9,21) 
varname<-c("lon","lat","pft","pft_wtgcell","pft_wtcol","FSR") 
files<-matrix(data=NA, nrow=12, ncol=length(varname)) 
#loop to cycle through the file starts here: 
i<-1 

#crate data.frame for lon, lat and pft 
newname<-paste(c("Y2005", numlist[i],".", varname[1]), collapse='') 
coord<-expand.grid(temp$lon, temp$lat, temp$pft) 
assign(newname, coord) 
files[i,1]<-newname 
#loop through the variables of interest 
# could probly be simplified. 
for (j in 4:length(varname)) { 
    newname<-paste(c("Y2005", numlist[i],".", varname[j]), collapse='') 
    assign(newname, as.data.frame.table(temp[[varname[j] ]])$Freq) 
    files[i,j]<-newname 
} 

私は、データフレームにサンプルデータの変換を回避し、直接作業することにしていますリストに表示されます。 expand.grid関数は、lon、latおよびpftの可能なすべての組み合わせのデータフレームを素早く作成します。 3D配列を平坦化する方法のヒントを検索すると、この場合に機能するas.data.frame.table関数への参照が見つかりました。また、最後の(平坦化された)データ列を格納しています。必要なデータだけがdata.frameに格納されるので、rbindsもより速く実行する必要があります。

私はエラーについて幅広いチェックを行っていませんが、私のラップトップでは、上記のテストケースの速度が500倍向上しました。

これがうまくいく場合は答えを受け入れてください。そうでない場合は、もう少し微調整できます。ここで

+0

確かにこの問題は 'assign'を使わなければ解決できます。 –

+0

はい、私はassignステートメントを使わないほうがいいでしょうが、元のコード結果の "ファイル"マトリックスを作成するために使用しました。私はそれを残しました。 – Dave2e

+0

ありがとう、これは非常に便利です!私はそれをそのまま使用することはできません。なぜなら、lat、lon、およびpftもncdefファイルから読み込むことができる必要があるからですが、最初にそれらを読み込んでから、 "coord"を作成するために使うことができるかもしれません。あなたは上に示した。 –

0

は、私はあなたがプロセス改善を探している場合は、あなたのコードの多くを投稿することができます@ Dave2eの助け

#Library Settings #------------------------------------------------------------------------------------ 
library(RNetCDF);library(data.table);library(plyr); library(arrayhelpers) 
#File Settings #--------------------------------------------------------------------------------------- 
setwd("C:/Users/User/Box Sync/_PhD/PhD_Research/Albedo/Data_CLM/PFTRuns/2005/") 
fname<-"b40.20th.1deg.bdrd.002bc.clm2.h0.2005-" 
numlist<-c('01','02','03','04','05','06','07','08','09','10','11','12') 
varlist<-c(1,2,4,8,9,21) 
varname<-c("lon","lat","pft","pft_wtgcell","pft_wtcol","FSR") 
files<-matrix(data=NA,ncol=12) 

for (i in 1:12) { 
    temp<- paste(c(fname, numlist[i],'.nc'), collapse='') 
    temp<-read.nc(open.nc(temp)) 
    for (j in 1:3){ 
    vars<-temp[[varlist[j]]] 
    newname<-paste(c("Y2005",".", varname[j]), collapse='') 
    assign(newname, vars)} 
    coord<-expand.grid(Y2005.lon, Y2005.lat, Y2005.pft) 
    coord$month<-c(numlist[i]) 
    newname<-paste(c("Y2005", numlist[i]), collapse=''); assign(newname, coord) 
    for (j in 4:length(varlist)){ 
    temp2<-array2df(temp[[varlist[j]]], label.x=varname[j]) 
    assign(newname, cbind(temp2, get(newname)))} 
    files[i]<-newname} 
Y2005<-lapply(files, cbind)