簡體   English   中英

R:使用IFELSE替代方法創建數據幀的最快方法

[英]R: Quickest way to create dataframe with an alternative to IFELSE

我有一個類似的問題,就是這個帖子: 使用R,將矩陣<0.1中的所有值替換為0?

但就我而言,我假設有更大的數據集和可變閾值。 我需要使用同一數據幀的第一列上的值創建一個數據框,其中包含從條件中檢索的每個值。 每行的這些值都不同。

以下是數據幀的示例:

SNP        A1  A2   MAF     
rs3094315  G   A   0.172  
rs7419119  G   T   0.240  
rs13302957 G   A   0.081  
rs6696609  T   C   0.393 

以下是我的代碼示例:

seqIndividuals = seq(1:201)
for(i in seqIndividuals) {
  alFrequ[paste("IND",i,"a",sep="")] = ifelse(runif(length(alFrequ$SNP),0.00,1.00) < alFrequ$MAF, alFrequ$A1, alFrequ$A2)
  alFrequ[paste("IND",i,"b",sep="")] = ifelse(runif(length(alFrequ$SNP),0.00,1.00) < alFrequ$MAF, alFrequ$A1, alFrequ$A2)
}

我在“seqIndividuals”中為每個“i”創建了兩個新列,如果隨機值低於列“MAF”,則檢索“A1”列中的值,如果更高,則檢索“A2”。 代碼工作得很好,但隨着數據集在行和列(個體)中的增長,時間也會顯着增長。

有沒有辦法避免在這種情況下使用IFELSE,因為據我所知它可以作為一個循環? 我嘗試生成隨機值矩陣然后替換它們,但它需要相同的時間甚至更長。

mtxAlFrequ = matrix(runif(length(alFrequ$SNP)*(201)),nrow=length(alFrequ$SNP),ncol=201)
mtxAlFrequ[mtxAlFrequ < alFrequ$MAF] = alFrequ$A1

謝謝!

一個選項是data.table

library(data.table)
nm1 <- paste0("IND", rep(letters[1:2], length(seqIndividuals)), 
                    rep(seqIndividuals, each = 2))
setDT(alFrequ)
for(j in seq_along(nm1)) {
      alFrequ[, nm1[j] := A2
             ][runif(.N, 0, 1) < MAF , nm1[j] := A1][]
}

基准

set.seed(24)
alFrequ <- data.frame(SNP= paste0('rs', sample(600000, 340000, replace=FALSE)),
                   A1 = sample(c("G", "T", "A", "C"), 340000, replace=TRUE),
                   A2 = sample(c("G", "T", "A", "C"), 340000, replace=TRUE),
                   MAF = runif(340000, 0, 1), stringsAsFactors=FALSE)
nm1 <- paste0("IND", rep(letters[1:2], length(seqIndividuals)), 
                          rep(seqIndividuals, each = 2))

system.time({
    setDT(alFrequ)
     for(j in seq_along(nm1)){
     alFrequ[, nm1[j] := A2][runif(.N, 0, 1) < MAF , nm1[j] := A1][]
   }
})
#   user  system elapsed 
#  10.72    1.05   11.76 

並在原始數據集上使用OP的代碼

system.time({
 for(i in seqIndividuals) {
   alFrequ[paste("IND",i,"a",sep="")] = ifelse(runif(length(alFrequ$SNP),0.00,1.00) < 
          alFrequ$MAF, alFrequ$A1, alFrequ$A2)
   alFrequ[paste("IND",i,"b",sep="")] = ifelse(runif(length(alFrequ$SNP),0.00,1.00) < 
             alFrequ$MAF, alFrequ$A1, alFrequ$A2)
 }
})
#    user  system elapsed 
#   72.16    6.82   79.33 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM