我想通過使用data.table作爲參數使用data.table的行應用函數。我目前正在使用apply建議here使用列作爲參數在data.table中使用行應用函數
但是,我的data.table是7列2700萬行,所以申請操作需要很長時間,當我在許多輸入文件遞歸運行時,作業佔用所有可用RAM(32Gb)。我很可能多次複製data.table,儘管我不確定這一點。
我希望能幫助這個代碼更高效的存儲,因爲每個輸入文件將是〜7千行〜7千行,並且有30個輸入文件要處理。我確信使用apply的行會減慢整個代碼的速度,所以更具內存效率或使用向量化函數的替代方法可能會是更好的選擇。
我在試圖編寫一個向量化函數時遇到了很多麻煩,它使用4列作爲參數,並使用data.table逐行操作。我的示例代碼中的應用解決方案有效,但速度很慢。一種替代方法我試過是:
cols=c("C","T","A","G")
func1<-function(x)x[max1(x)]
datU[,high1a:=func1(cols),by=1:nrow(datU)]
但第6行督data.table輸出看起來像這樣的:
Cycle Tab ID colA colB colC colG high1 high1a
1 0 45513 -233.781 -84.087 -3.141 3740.916 3740.916 colC
2 0 45513 -103.561 -347.382 2900.866 357.071 2900.866 colC
3 0 45513 153.383 4036.636 353.479 -42.736 4036.636 colC
4 0 45513 -147.941 28.994 4354.994 384.945 4354.994 colC
5 0 45513 -89.719 -504.643 1298.476 131.32 1298.476 colC
6 0 45513 -250.11 -30.862 1877.049 -184.772 1877.049 colC
下面是一個使用應用該作品在我的代碼(它產生的高溫1列以上),但過於緩慢和內存密集型:
#Get input files from top directory, searching through all subdirectories
file_list <- list.files(pattern = "*.test.txt", recursive=TRUE, full.names=TRUE)
#Make a loop to recursively read files from subdirectories, determine highest and second highest values in specified columns, create new column with those values
savelist=NULL
for (i in file_list) {
datU <- fread(i)
name=dirname(i)
#Compute highest and second highest for each row (cols 4,5,6,7) and the difference between highest and second highest values
maxn <- function(n) function(x) order(x, decreasing = TRUE)[n]
max1 <- maxn(1)
max2 <- maxn(2)
colNum=c(4,5,6,7)
datU[,high1:=apply(datU[,colNum,with=FALSE],1,function(x)x[max1(x)])])
datU[,high2:=apply(datU[,colNum,with=FALSE],1,function(x)x[max2(x)])]
datU[,difference:=high1-high2,by=1:nrow(datU)]
datU[,folder:=name]
savelist[[i]]<-datU
}
#Create loop to iterate over folders and output data
sigout=NULL
for (i in savelist) {
# Do some stuff to manipulate data frames, then merge them for output
setkey(i,Cycle,folder)
Sums1<-i[,sum(colA,colB,colC,colD),by=list(Cycle,folder)]
MeanTot<-Sums[,round(mean(V1),3),by=list(Cycle,folder)]
MeanTotsd<-Sums[,round(sd(V1),3),by=list(Cycle,folder)]
Meandiff<-i[,list(meandiff=mean(difference)),by=list(Cycle,folder)]
Meandiffsd<-i[,list(meandiff=sd(difference)),by=list(Cycle,folder)]
df1out<-merge(MeanTot,MeanTotsd,by=list(Cycle,folder))
df2out<-merge(Meandiff,Meandiffsd,by=list(Cycle,folder))
sigout<-merge(df1out,df2out)
#Output values
write.table(sigout,"Sigout.txt",append=TRUE,quote=FALSE,sep=",",row.names=FALSE,col.names=TRUE)
}
我喜歡關於替代的功能應用,這將使我的最高和次高值,每一行對C一些例子第4,5,6,7列可以通過索引或列名來識別。
謝謝!
羅蘭,謝謝你的幫助!我能夠成功地在2〜3000萬行輸入文件上使用您的代碼。但是,這段代碼在運行時使用了大約14Gb的RAM。是否有可能對諾羅打電話是什麼東西吃掉所有的內存?我擔心如果我在30個輸入文件上試試這個,我仍然會用完RAM。我會盡快開始,讓你知道它是如何發展的。 – krisadastra
當我嘗試使用我的30個輸入文件運行代碼時,我遇到了內存分配錯誤:'錯誤:無法分配大小爲310的向量。8 Mb 此外:警告消息: 1:在forderv(byval,sort = FALSE,retGrp = TRUE): 達到32675Mb的總分配:see help(memory.size)'看起來這個代碼不是內存有效,因爲我需要它。 savelist對象只有14個元素,而不是30個,但已經是31.1Gb的大小。 – krisadastra