【问题标题】:Use 'apply' instead of a nested loop on two matrices [duplicate]在两个矩阵上使用“应用”而不是嵌套循环[重复]
【发布时间】:2017-08-11 00:28:43
【问题描述】:

我有两个矩阵:

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 教程和问题。所以我知道我的解决方案需要使用apply,但尽我所能,我不明白如何实际编写它。我看到的所有示例都非常简单,涉及查找列或行的总和或平均值。 问题是:

一个。我需要一个“应用”,它可以容纳一个接收两个变量的函数,每个矩阵的一行。这需要一些操作来检索行。我可以解决这个问题:

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

但我不知道如何将其插入“应用”

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

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

我不在乎列是否有名称。

任何解决方案、提示或参考将不胜感激:-)

【问题讨论】:

  • cor(t(first.matrix), t(second.matrix)),然后是reshape2::melt(cor(t(first.matrix), t(second.matrix)))
  • 哇!!太优雅了!如果你把它写成一个解决方案,我会接受它。我不知道“cor”会在转置矩阵上执行。现在我很好奇:这背后的直觉是什么?我怎么会知道呢?我直接在矩阵上尝试了“cor”,这当然没有用。非常感谢!
  • “使用 '*apply' 系列而不是循环/嵌套循环”的通用术语是 vectorization。请在此类问题上使用该标签。并略读现有的问题。 R 中的一般理念是,大多数函数应该允许使用向量/矩阵参数而不是单个数字,这是有意义的。
  • @smci - 我阅读(不是略读,花时间阅读)我在apply 上找到的所有问题,并且我还阅读了一些教程。我还阅读了答案,cmets和cmets上的cmets,几乎总是出现像你这样的评论。我尽力以“正确的方式”提出问题。请注意,我在原始问题中的“类 java”R 代码确实在向量上使用了cor(我知道一个函数允许多个数字),但我没有想到我可以转置矩阵和然后将列称为向量。很明显,当我现在重新考虑时。
  • @nafrtiti :当然,你没有做错任何事,我不是说你做错了!只是想确保你知道'vectorize'是下一次的正确关键字,并且循环通常要避免的R哲学,应该可以用向量/矩阵替换,并用你需要的任何其他功能机器包装。当我最初从 Python 迁移时,我花了很多时间来适应。来自 Java 的范式转变更加困难。

标签: r matrix vectorization apply correlation


【解决方案1】:

一种解决方案是首先将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

【讨论】:

  • 不好意思说我不太理解这个解决方案,因为我没有看到rows的定义,所以不明白它是如何工作的。
  • @nafrtiti 那是我的错我很抱歉 - 我没有更新代码中的名称。 rows 应该是 res。现在应该可以工作了。
  • 感谢您的澄清!
【解决方案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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-05-10
    • 1970-01-01
    • 1970-01-01
    • 2021-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多