【问题标题】:Efficiently applying conditions to a matrix有效地将条件应用于矩阵
【发布时间】:2017-08-01 08:52:37
【问题描述】:

我有一个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)中获取的某个测量的计数,这些实验在 data.framelist 中进行了描述:

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))

df.list 中每个data.frame 中的列是其相应实验的因子,这些列的值是因子水平。 counts.matcolnames 是这些因子水平的复制品,它们的名称遵循以下格式:

&lt;factor.level&gt;_&lt;replicate&gt;

这对应于df.list

例如,df.list$df1 中的gt1 是一个带有级别的因子:

"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 &lt;- 1

min.counts &lt;- 10

我想做的是针对每个因素(列),在每个 data.framedf.list 返回 TRUEFALSE 如果至少 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)
        })))
      })))
    })))
}))

所以我正在寻找更快的东西。

【问题讨论】:

  • 在您的counts.mat 中有重复的列名wm.3m_1wm.3m_2 - 倒数第二行的列名应该是2m 而不是3m
  • 抱歉 - 已修复

标签: r matrix dataframe apply do.call


【解决方案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

【讨论】:

    猜你喜欢
    • 2020-12-17
    • 2011-05-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多