Эффективное применение условий к матрице

У меня есть integer matrix:

set.seed(1)
counts.mat <- matrix(sample(50,29*10,replace=T),nrow=10,ncol=29)
colnames(counts.mat) <- c("ww.1m_1","ww.1m_2","wm.1m_1","wm.1m_2","wm.1m_3","wn.1m_1","wn.1m_2",
"A_1","A_2","B_1","B_2","C_1","C_2",
"ww.2m_1","ww.2m_2","ww.2m_3","wm.2m_1","wm.2m_2","wn.2m_1","wn.2m_2",
"ww.3m_1","ww.3m_2","ww.3m_3","wm.3m_1","wm.3m_2","wm.3m_3","wn.3m_1","wn.3m_2","wn.3m_3")

Его элементы представляют собой подсчеты определенного измерения, взятые из набора экспериментов (в этом примере 3), которые описаны в этом list из data.frame:

df.list <- list(df1 = data.frame(gt1=c("ww.1m","wm.1m","wn.1m"),kt1=c("A","B","C"),stringsAsFactors=F),
                df2 = data.frame(gt2=c("ww.2m","wm.2m","wn.2m"),stringsAsFactors=F),
                df3 = data.frame(gt2=c("ww.3m","wm.3m","wn.3m"),stringsAsFactors=F))

Столбцы в каждом data.frame в df.list — это факторы соответствующего эксперимента, а значения этих столбцов — это уровни факторов. colnames из counts.mat являются копиями этих уровней факторов, и их имена имеют следующий формат:

<factor.level>_<replicate>.

Это соответствует им df.list.

Например, gt1 в df.list$df1 — фактор с уровнями:

"ww.1m" "wm.1m" "wn.1m"

чьи соответствующие реплики в counts.mat:

"ww.1m_1","ww.1m_2","wm.1m_1","wm.1m_2","wm.1m_3","wn.1m_1","wn.1m_2"

Данный:

min.replicates <- 1

min.counts <- 10

то, что я хочу сделать, это для каждого фактора (столбца) в каждом data.frame в df.list вернуть TRUE или FALSE, если по крайней мере min.replicates или более имеют по крайней мере min.counts или более для каждой строки в counts.mat.

Результат должен быть matrix, где количество столбцов равно общему количеству уровней фактора df.list, а количество строк равно количеству строк counts.mat.

Вот что я считаю медленной реализацией:

res.mat <- do.call(rbind,lapply(1:nrow(counts.mat),function(i){
  return(do.call(cbind,lapply(1:length(df.list),function(l){
    return(do.call(cbind,lapply(1:ncol(df.list[[l]]),function(j){
      return(do.call(cbind,lapply(1:nrow(df.list[[l]]),function(k){
        return(length(which(counts.mat[i,which(grepl(paste0(df.list[[l]][k,j],"_\\d+$"),colnames(counts.mat),perl=T))] >= min.counts)) >= min.replicates)
        })))
      })))
    })))
}))

Поэтому я ищу что-то значительно быстрее.


person dan    schedule 01.08.2017    source источник
comment
В вашем counts.mat у вас есть повторяющиеся имена столбцов wm.3m_1 и wm.3m_2 — должны ли они в предпоследней строке быть 2m, а не 3m?   -  person Andrew Gustar    schedule 01.08.2017
comment
Извините за это - исправлено   -  person dan    schedule 01.08.2017


Ответы (1)


Я думаю, что это делает то же самое, и должно быть быстрее...

dfcols <- unlist(df.list) #extract list of columns required as a vector
matcols <- lapply(dfcols,function(x) which(startsWith(colnames(counts.mat),x))) #match to matrix columns
resmat <- sapply(1:length(dfcols),function(i) 
        apply(counts.mat[,matcols[[i]]],1,function(y) sum(y>=min.count) >= min.replicates))
colnames(resmat) <- dfcols #set colnames in output

С исправлением в моем комментарии выше и min.replicates, установленным на 30 (все элементы равны TRUE, если они равны 10, в вашем примере), это дает...

resmat
      ww.1m wm.1m wn.1m     A     B     C ww.2m wm.2m wn.2m ww.3m wm.3m wn.3m
 [1,] FALSE  TRUE  TRUE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE
 [2,] FALSE  TRUE  TRUE  TRUE FALSE  TRUE  TRUE  TRUE FALSE FALSE  TRUE FALSE
 [3,]  TRUE  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE
 [4,]  TRUE FALSE FALSE FALSE  TRUE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
 [5,]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE  TRUE
 [6,]  TRUE  TRUE FALSE  TRUE  TRUE FALSE  TRUE  TRUE  TRUE FALSE  TRUE FALSE
 [7,]  TRUE  TRUE FALSE  TRUE FALSE  TRUE FALSE  TRUE  TRUE  TRUE  TRUE FALSE
 [8,]  TRUE FALSE  TRUE FALSE FALSE FALSE  TRUE  TRUE  TRUE  TRUE FALSE  TRUE
 [9,]  TRUE  TRUE  TRUE  TRUE  TRUE FALSE  TRUE  TRUE  TRUE  TRUE FALSE  TRUE
[10,]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
person Andrew Gustar    schedule 01.08.2017