2014-10-18 144 views
-1

因此,我有這個功能可以將來自多個探針的測量值歸入定義的區域。使用具有自定義功能的%dopar%

HMkit.dmr<-function(Mat,Classes,method.fdr=c("BH","bonferroni"),probe.features) { 

    #Annotate first... 
    require(plyr) 
    require(dplyr) 


    #Filter matrix for testing and stuff... 

    message("Setting up merged table") 
    Mat2<-Mat[match(probe.features$probe,rownames(Mat)),] 

    #Split by classes 

    if(!is.factor(Classes)) { 
     Classes<-as.factor(Classes) 
    } 
    Class.1<-levels(Classes)[[1]] 
    Class.2<-levels(Classes)[[2]] 

    C1.Mat<-Mat2[,Classes==Class.1] 
    C2.Mat<-Mat2[,Classes==Class.2] 

    #Summarise and run wilcoxon's test for each dmr... 
    num.regions<-length(unique(as.character(probe.features$region.id))) 
    pvals.vec<-numeric(length=num.regions) 
    unique.regions<-unique(as.character(probe.features$region.id)) 
    message(num.regions) 
    Meds.1<-numeric(length=num.regions);Meds.2<-numeric(length=num.regions) 

    for (i in 1:num.regions) { 
     region<-probe.features%>%filter(region.id %in% unique.regions[[i]]) 
     Set1.Mat<-as.numeric(C1.Mat[rownames(C1.Mat) %in% region$probe,]) 
     Set2.Mat<-as.numeric(C2.Mat[rownames(C2.Mat) %in% region$probe,]) 
     pvals.vec[[i]]<-wilcox.test(Set1.Mat,Set2.Mat)$p.value 
     Meds.1[[i]]<-median(Set1.Mat) 
     Meds.2[[i]]<-median(Set2.Mat) 
     message(i) 
    } 

    #Output frame 
    dmrs.frame<-data.frame(region=unique.regions,pval=pvals.vec,G1=Meds.1,G2=Meds.2,dB=Meds.1-Meds.2) 
    dmrs.frame$q.val<-p.adjust(dmrs.frame$pval,method=method.fdr) 
    groups.ids<-levels(Classes) 
    return(list(dmrs=dmrs.frame,groups=groups.ids)) 
} 

代碼基本上由樣品分割矩陣分成兩組,然後拉動被定義爲在一個區域是所有探針的值,調用一個wilcox.test和中值概要步驟,它使用給填充事先創建的向量。

我試圖用foreach包中的doparallel函數替換for循環中的for,但一直沒有能夠用正確的結果填充矢量。我想知道如何正確使用上述函數的並行化 - 通過修改for循環或修改函數調用,以便區域被分解爲並行處理的塊。

實例對象按照以下...

Mat<-matrix(runif(200,0,1), ncol=10,nrow=20) 
rownames(Mat)<-paste0("p",1:20) 
colnames(Mat)<-paste0("S",1:10) 

Classes<-as.character(c(rep("G1",6),rep("G2",4))) 
probe.features<-data.frame(probe=paste0("p",1:20),region.id=c(rep("R1",5),rep("R2",3),rep("R3",4),rep("R5",4),rep("R6",4)) 

和功能使用

x<-HMkit.dmr(Mat,Classes,method.fdr=c("BH"),probe.features=probe.features) 

在實踐中運行,有30000米的區域我在看,並希望跨parallelise功能Windows上有多個核心,因爲串行執行可能需要長達40分鐘。我該怎麼做呢?

增編 - 我試圖與

library(doParallel) 
ncores<-2 
Cl<-makeCluster(2) 
registerDoParallel(Cl) 
x<-foreach(i=1:length(unique(probe.features$region.id)),packages=c("plyr","dplyr"))%dopar%HMkit.dmr(Mat,Classes,probe.features=probe.features,method.fdr="BH") 

但是要做到這一點,這樣做只是返回相同的結果串行功能的兩個副本,我想要它做的是在probe.features打破地區$ region.id分成不同的核心。

回答

0

在我看來,你的「for」循環可以很容易並行化。它只是建立三個向量,每次迭代一個元素,每個向量將成爲「dmrs.frame」的列。所以每個迭代計算結果的一行。

要使用「foreach」,您可以簡單地將這三個值連接成一個向量。該.combine選項用於所有這些向量與「rbind」合併爲一個矩陣:

m <- foreach(uregion=unique.regions, .combine='rbind', 
      .packages=c('plyr', 'dplyr')) %dopar% { 
    region<-probe.features%>%filter(region.id %in% uregion) 
    Set1.Mat<-as.numeric(C1.Mat[rownames(C1.Mat) %in% region$probe,]) 
    Set2.Mat<-as.numeric(C2.Mat[rownames(C2.Mat) %in% region$probe,]) 
    c(wilcox.test(Set1.Mat, Set2.Mat)$p.value, 
     median(Set1.Mat), median(Set2.Mat)) 
} 

我擺脫了「我」的變量,因爲我認爲這是更具可讀性簡單過的元素迭代「 unique.regions」。

現在你可以創建 「dmrs.frame」 使用矩陣 「M」 列:

dmrs.frame <- data.frame(region=unique.regions, 
     pval=m[,1] G1=m[,2] G2=m[,3], dB=m[,2]-m[,3]) 
+0

謝謝你史蒂夫,工作出色 - 雖然在dmrs.frame <-data.frame下標(.. )需要交換來指示列而不是行。 – 2014-11-12 15:51:22

+0

@AnkurChakravarthy謝謝你指出。它現在應該在我的答案中得到解決。 – 2014-11-12 16:58:54