-1

我有这样的矩阵:我想对具有相同名称的列进行分组,并将函数应用于矩阵的行。

>data

      A  A  A  B  B  C
gene1 1  6 11 16 21 26
gene2 2  7 12 17 22 27
gene3 3  8 13 18 23 28
gene4 4  9 14 19 24 29
gene5 5 10 15 20 25 30

基本上,我想将具有相同名称的列放在A1组、B2 组......之后,我计算所有组的每个基因的 T 检验。谁能帮助我我该怎么做?首先:分组,然后应用 T 检验,返回不同组之间每个基因的 T 分数。

4

1 回答 1

4

OP 没有提到他们在输出中想要什么形式,但我正在用一个可能的解决方案完全更新这个答案。

首先,一些可重现的样本数据可以使用(实际上可以使用t.test)。

set.seed(1)
mymat <- matrix(sample(100, 40, replace = TRUE), 
                ncol = 8, dimnames = list(
                  paste("gene", 1:5, sep = ""), 
                  c("A", "A", "A", "B", "B", "B", "C", "C")))
mymat
#        A  A  A   B  B  B  C  C
# gene1 27 90 21  50 94 39 49 67
# gene2 38 95 18  72 22  2 60 80
# gene3 58 67 69 100 66 39 50 11
# gene4 91 63 39  39 13 87 19 73
# gene5 21  7 77  78 27 35 83 42

我已经把所有的辛苦工作都交给了这个combn函数。在combn函数中,我利用FUN参数添加了一个函数,该函数按每行创建一个t.test“统计”向量(我假设每行一个基因)。我还在attribute结果向量中添加了一个,以提醒我们在计算统计数据时使用了哪些列。

temp <- combn(unique(colnames(mymat)), 2, FUN = function(x) {
  out <- vector(length = nrow(mymat))
  for (i in sequence(nrow(mymat))) {
    out[i] <- t.test(mymat[i, colnames(mymat) %in% x[1]], 
           mymat[i, colnames(mymat) %in% x[2]])$statistic
  }
  attr(out, "NAME") <- paste(x, collapse = "")
  out
}, simplify = FALSE)

上面的输出是一个listvectors将其转换为matrix. 由于我们知道向量中的每个值代表一行,并且每个向量总体上代表一个列值组合(AB、AC 或 BC),因此我们可以将其用于dimnames结果的matrix.

DimNames <- list(rownames(mymat), sapply(temp, attr, "NAME"))

final <- do.call(cbind, temp)
dimnames(final) <- DimNames
final
#               AB         AC           BC
# gene1 -0.5407966 -0.5035088  0.157386919
# gene2  0.5900350 -0.7822292 -1.645448267
# gene3 -0.2040539  1.7263502  1.438525163
# gene4  0.6825062  0.5933218  0.009627409
# gene5 -0.4384258 -0.9283003 -0.611226402

一些手动验证:

## Should be the same as final[1, "AC"]
t.test(mymat[1, colnames(mymat) %in% "A"],
       mymat[1, colnames(mymat) %in% "C"])$statistic
#          t 
# -0.5035088 

## Should be the same as final[5, "BC"]    
t.test(mymat[5, colnames(mymat) %in% "B"],
       mymat[5, colnames(mymat) %in% "C"])$statistic
#          t 
# -0.6112264 

## Should be the same as final[3, "AB"]
t.test(mymat[3, colnames(mymat) %in% "A"],
       mymat[3, colnames(mymat) %in% "B"])$statistic
#          t 
# -0.2040539 

更新

基于@EDi 的回答,这是另一种方法。它利用meltfrom "reshape2" 将数据转换为 "long" 格式。从那里开始,和以前一样,得到你想要的东西是非常简单的子集工作。那里的输出相对于纯combn方法采用的方法进行了转置,但值是相同的。

library(reshape2)
mymatL <- melt(mymat)

byGene <- split(mymatL, mymatL$Var1)
RowNames <- combn(unique(as.character(mymatL$Var2)), 2, 
                  FUN = paste, collapse = "")

out <- sapply(byGene, function(combos) {
  combn(unique(as.character(mymatL$Var2)), 2, FUN = function(x) {
    t.test(value ~ Var2, combos[combos[, "Var2"] %in% x, ])$statistic
  }, simplify = TRUE)
})

rownames(out) <- RowNames
out
#         gene1      gene2      gene3       gene4      gene5
# AB -0.5407966  0.5900350 -0.2040539 0.682506188 -0.4384258
# AC -0.5035088 -0.7822292  1.7263502 0.593321770 -0.9283003
# BC  0.1573869 -1.6454483  1.4385252 0.009627409 -0.6112264

第一个选项要快得多,至少在这个较小的数据集上:

microbenchmark(fun1(), fun2())
# Unit: milliseconds
#    expr       min        lq    median       uq      max neval
#  fun1()  8.812391  9.012188  9.116896  9.20795 17.55585   100
#  fun2() 42.754296 43.388652 44.263760 45.47216 67.10531   100
于 2013-10-02T09:44:36.707 回答