在两个矩阵上使用'apply'而不是嵌套循环

时间:2017-03-19 20:00:14

标签: r matrix vectorization apply correlation

我有两个矩阵:

first.matrix  = matrix(c(1,1,2,3,3,2,4,1), nrow=2)
second.matrix = matrix(c(2,2,3,3,1,1,4,1), nrow=2)

我希望找到'first.matrix'中的行与second.matrix中的行之间的相关性。在Java中,我会写这样的东西:

results <- data.frame("first"=c(1:4),"second"=c(1:4), "cor"=c(1:4))
counter <- 1
for(i in 1:2) {
  a <- c(t(first.matrix[i,]))
  for(j in 1:2) {
    b <- c(t(second.matrix[j,]))    
    results$cor[counter] <- cor(a,b)
    results$first[counter]  <- i
    results$second[counter] <- j
    counter=counter+1
  }  
}

我正在尝试以“正确”的方式自学R代码,并花时间在Stack Overflow上阅读R-tutorials和问题。所以我知道我的解决方案需要使用apply,但尽可能地尝试,我不明白如何实际编写它。我看到的所有示例都非常简单,涉及查找列或行的总和或平均值。 问题是:

一个。我需要一个'apply',它可以容纳一个接收两个变量的函数,每个矩阵都有一行。这需要一点操作来检索行。我可以用以下方法解决这个问题:

c(t(first.matrix[i,]))

但我不知道如何将其插入'apply'

湾我需要结果告诉我第一个矩阵中的哪一行与第二个矩阵中的哪一行进行比较,结果是什么。在我的例子中,运行我编写的代码将导致:

 first second        cor
1     1      1  0.4000000
2     1      2 -0.6741999
3     2      1 -0.1348400
4     2      2  0.6363636

我不在乎列是否有名字。

任何解决方案,提示或参考都将非常感激: - )

2 个答案:

答案 0 :(得分:2)

一种解决方案是首先将first.matrix的行数合并到second.matrix的行数中,以获得所需的所有组合。基本上这只是为您提供所需矩阵的索引。然后你可以做一个sapply来获得相关性。

类似的东西:

    res<-merge(data.frame(first=1:nrow(first.matrix)),
               data.frame(second=1:nrow(second.matrix)))
    res$corr<-sapply(1:nrow(res),function(i) {
                        cor(first.matrix[res[i,1],],second.matrix[res[i,2],])
                        })
    res

#   first second       corr
#1     1      1  0.4000000
#2     2      1 -0.1348400
#3     1      2 -0.6741999
#4     2      2  0.6363636

答案 1 :(得分:2)

您可以将expand.gridapply合并来实现此目的。使用expand.grid获取包含两个矩阵中所有可能的行组合的表格,然后使用apply在这些组合上迭代您的函数。像:

apply(# get a table with all possible combinations of rows
      expand.grid(seq(nrow(first.matrix)), seq(nrow(second.matrix))),
      # apply the upcoming function row-wise
      1,
      # now run cor over those combos of row
      function(x) cor(x = first.matrix[x[1],], y = second.matrix[x[2],]))

结果:

[1]  0.4000000 -0.1348400 -0.6741999  0.6363636