2013-09-21 34 views
1

我想應用一個函數返回一個矩陣大型data.table對象的每一行(原始文件大約30 GB ,我有80 GB RAM),然後找回一個data.table對象。我想要有效地做到這一點。我目前的做法是:應用函數返回一個data.table,或直接將列表轉換爲data.table

my.function <- function(x){ 
    alnRanges<-cigarToIRanges(x[6]); 
    alnStarts<-start(alnRanges)+as.numeric(x[4])-1; 
    alnEnds<-end(alnRanges)+as.numeric(x[4])-1; 
    y<-x[-4]; 
    ys<-matrix(rep(y,length(alnRanges)),nrow=length(alnRanges),ncol=length(y),byrow=TRUE); 
    ys<-cbind(ys,alnStarts,alnEnds); 
    return(ys);  # ys is a matrix 
} 

    my.dt<-fread(my.file.name); 
    my.list.of.matrices<-apply(my.dt,1,my.function); 
    new.df<-do.call(rbind.data.frame,my.list.of.matrices); 
    colnames(new.df)[1:14]<-colnames(my.dt)[-4]; 
    new.dt<-as.data.table(new.df); 

注1:我指定的my.function只是爲了表明它返回一個矩陣,而我的申請,因此線是矩陣的列表。注2:我不知道我正在做的操作有多慢,但似乎我可以減少行數。例如,將數據框轉換爲大型對象的數據表是否慢?

重複的例子:

注意,阿倫和羅蘭讓我想到這個問題,所以我仍然在它的工作...可能是我不需要這些行難...

我想要取得一個sam文件,然後創建一個新的座標文件,每個讀取根據其CIGAR字段進行拆分。

My sam file: 
qname rname pos cigar 
2218 chr1 24613476 42M2S 
2067 chr1 87221030 44M 
2129 chr1 79702717 44M 
2165 chr1 43113438 44M 
2086 chr1 52155089 4M921N40M 

code: 

library("data.table"); 
library("GenomicRanges"); 

sam2bed <- function(x){ 
    alnRanges<-cigarToIRanges(x[4]); 
    alnStarts<-start(alnRanges)+as.numeric(x[3])-1; 
    alnEnds<-end(alnRanges)+as.numeric(x[3])-1; 
    #y<-as.data.frame(x[,pos:=NULL]); 
    #ys<-y[rep(seq_len(nrow(y)),length(alnRanges)),]; 
    y<-x[-3]; 
    ys<-matrix(rep(y,length(alnRanges)),nrow=length(alnRanges),ncol=length(y),byrow=TRUE); 
    ys<-cbind(ys,alnStarts,alnEnds); 
    return(ys); 
} 


sam.chr.dt<-fread(sam.parent.chr.file); 
setnames(sam.chr.dt,old=c("V1","V2","V3","V4"),new=c("qname","rname","pos","cigar")); 
bed.chr.lom<-apply(sam.chr.dt,1,sam2bed); 
> bed.chr.lom 
[[1]] 
          alnStarts alnEnds 
[1,] "2218" "chr1" "42M2S" "24613476" "24613517" 

[[2]] 
         alnStarts alnEnds 
[1,] "2067" "chr1" "44M" "87221030" "87221073" 

[[3]] 
         alnStarts alnEnds 
[1,] "2129" "chr1" "44M" "79702717" "79702760" 

[[4]] 
         alnStarts alnEnds 
[1,] "2165" "chr1" "44M" "43113438" "43113481" 

[[5]] 
           alnStarts alnEnds 
[1,] "2086" "chr1" "4M921N40M" "52155089" "52155092" 
[2,] "2086" "chr1" "4M921N40M" "52156014" "52156053" 

bed.chr.df<-do.call(rbind.data.frame,bed.chr.lom); 

> bed.chr.df 
    V1 V2  V3 alnStarts alnEnds 
1 2218 chr1  42M2S 24613476 24613517 
2 2067 chr1  44M 87221030 87221073 
3 2129 chr1  44M 79702717 79702760 
4 2165 chr1  44M 43113438 43113481 
5 2086 chr1 4M921N40M 52155089 52155092 
6 2086 chr1 4M921N40M 52156014 52156053 

bed.chr.dt<-as.data.table(bed.chr.df); 

> bed.chr.dt 
    V1 V2  V3 alnStarts alnEnds 
1: 2218 chr1  42M2S 24613476 24613517 
2: 2067 chr1  44M 87221030 87221073 
3: 2129 chr1  44M 79702717 79702760 
4: 2165 chr1  44M 43113438 43113481 
5: 2086 chr1 4M921N40M 52155089 52155092 
6: 2086 chr1 4M921N40M 52156014 52156053 
+0

你不應該需要(並使用)'apply' data.table。目標應該是避免副本。請提供可複製的數據並解釋您實際嘗試做的事情。 – Roland

+0

@Roland,我需要將一個函數應用於data.table的每一行。如果我不應用apply,那麼我不知道我還能做什麼,我對數據表不熟悉,但我知道它們比數據框要快得多。試着製作一個例子...... – Dnaiel

+1

正如我所說的,提供一個工作示例(包括數據和必要的軟件包)並告訴我們你想實現什麼。如果你將它與'apply'混合使用,你將無法獲得data.table的優勢。 – Roland

回答

3

假設ff是你data.table,這個怎麼樣?

splits <- cigarToIRangesListByAlignment(ff$cigar, ff$pos, reduce.ranges = TRUE) 
widths <- width(attr(splits, 'partitioning')) 
cbind(data.table(qname=rep.int(ff$qname, widths), 
      rname=rep.int(ff$rname, widths)), as.data.frame(splits)) 

    qname rname space start  end width 
1: 2218 chr1  1 24613476 24613517 42 
2: 2067 chr1  2 87221030 87221073 44 
3: 2129 chr1  3 79702717 79702760 44 
4: 2165 chr1  4 43113438 43113481 44 
5: 2086 chr1  5 52155089 52155092  4 
6: 2086 chr1  5 52156014 52156053 40 
+0

非常感謝!很棒的建議。我也在研究rsamtools和iranges,因爲也許我可以將所有的代碼改爲這種方法......謝謝! – Dnaiel

相關問題