【问题标题】:R matrix/array sumproduct transformationR矩阵/数组和积变换
【发布时间】:2020-08-22 17:03:59
【问题描述】:

我正在尝试使用两个矩阵进行矩阵 sumproduct 计算。 sumproduct 是一个矩阵中的行与另一个矩阵中的列。

set.seed(123)
y <- matrix(sample(1:6,6,FALSE), nrow=3, ncol=2) 
x <- matrix(sample(1:5,15,TRUE), nrow=5, ncol=3)

> x
     [,1] [,2] [,3]
[1,]    5    4    3
[2,]    2    3    2
[3,]    2    3    3
[4,]    4    3    1
[5,]    3    5    5

> y
     [,1] [,2]
[1,]    3    4
[2,]    6    5
[3,]    2    1

结果中的 [1,1] 中的单元格值将是 x[ 1 , ] 和 y[ , 1] 的 sumproduct。 [1,2] 中的单元格值是 x[ 1 , ] 和 y[ , 2] 的和积。 [2,1] 中的单元格值是 x[ 2 , ] 和 y[ , 1] 的和积。等等。最终结果应该是这样的

> result

         [,1] [,2] 
    [1,]   45   43 
    [2,]   28   25 
    [3,]   30   26 
    [4,]   32   32 
    [5,]   49   42 

我可以使用循环来做到这一点,但如果有一个自动执行此操作的函数会容易得多。

【问题讨论】:

    标签: r arrays matrix sumproduct


    【解决方案1】:

    我会建议下一个方法。有一个名为crossprod() 的函数,但适用于矩阵的定义维度。你可以检查一下。下一个代码可能有用:

    set.seed(123)
    #Data
    y <- matrix(sample(1:6,6,FALSE), nrow=3, ncol=2) 
    x <- matrix(sample(1:5,15,TRUE), nrow=5, ncol=3)
    

    矩阵:

    x
         [,1] [,2] [,3]
    [1,]    5    5    1
    [2,]    4    3    1
    [3,]    1    3    5
    [4,]    2    1    3
    [5,]    3    4    2
    
    y
         [,1] [,2]
    [1,]    3    4
    [2,]    6    5
    [3,]    2    1
    

    代码:

    #Code
    z <-   t(sapply(1:nrow(x), function(i){
        x[i, ] %*% sapply(1:ncol(y), function(j) {y[,j]})}))
    

    输出:

    z
         [,1] [,2]
    [1,]   47   46
    [2,]   32   32
    [3,]   31   24
    [4,]   18   16
    [5,]   37   34
    

    【讨论】:

    • 可能遗漏了一些东西,但这只是x %*% y
    • @Duck,谢谢,太好了。我不知道你可以用 sapply 做到这一点。谢谢
    • @H.Cheung 不错!你现在知道该怎么做了!如果您认为这个答案对您有帮助,您可以接受:)这取决于您!
    • @Duck,Cole 的另一个回答也同样出色,所以不知道该怎么做。我在这里相当新,当两个答案同样好时,不知道这里的礼仪是什么?在我看来,你们都是赢家,但我会为你打勾!干杯
    • @user20650 - OMG。你是对的,这行得通!浏览所有建议的方法很有趣。至少有利于学习 R 的工作原理。谢谢
    【解决方案2】:

    这是一种使用outer 对矩阵索引进行运算符的方法。 Vectorize 允许我们在outer 中组合结果。如果您需要性能,我真的认为使用循环使用 会相对容易。

    set.seed(123)
    y <- matrix(sample(1:6,6,FALSE), nrow=3, ncol=2) 
    x <- matrix(sample(1:5,15,TRUE), nrow=5, ncol=3)
    
    outer(seq_len(nrow(x)),
          seq_len(ncol(y)),
          FUN  = Vectorize(function(i, j) sum(x[i, ] * y[, j])))
    #>      [,1] [,2]
    #> [1,]   47   46
    #> [2,]   32   32
    #> [3,]   31   24
    #> [4,]   18   16
    #> [5,]   37   34
    

    出于好奇,这需要大约 5 分钟才能提出 解决方案:

    #include <Rcpp.h>
    using namespace Rcpp;
    
    // [[Rcpp::export]]
    IntegerMatrix custom_crossprod(IntegerMatrix x, IntegerMatrix y) {
      int nrow = x.rows();
      int ncol = y.cols();
      IntegerMatrix ans(nrow, ncol);
      
      for (int i = 0; i < nrow; i++) {
        IntegerVector x_tmp = x(i, _);
        for (int j = 0; j < ncol; j++) {
          ans(i, j) = sum(x_tmp * y(_, j));
        }
      }
      return(ans);
    }
    

    基准测试::

    bench::mark(
      use_outer = 
    outer(seq_len(nrow(x)),
          seq_len(ncol(y)),
          FUN  = Vectorize(function(i, j) sum(x[i, ] * y[, j])))
    , custom_crossprod(x, y)
    )
    # A tibble: 2 x 13
    ##  expression                 min  median `itr/sec` mem_alloc `gc/sec`
    ##  <bch:expr>             <bch:t> <bch:t>     <dbl> <bch:byt>    <dbl>
    ##1 use_outer              179.8us 191.2us     4394.   11.73KB     4.37
    ##2 custom_crossprod(x, y)   4.9us   6.6us   135309.    2.49KB     0  
    

    【讨论】:

    • 谢谢,这是一个很好的解决方案,就像一个“for循环”,但不是。非常感谢
    • r 的大部分内容就像一个“for 循环”,但不是:)。很多循环都被隐藏了。
    • 我不知道。我写了类似于上面第二个代码的东西。我觉得编写循环是低效的,当似乎有功能可以做所有事情时。谢谢
    【解决方案3】:

    @user20650 提供了最合适的答案。

    看来 x %*% y 就足够了

    set.seed(123)
    y <- matrix(sample(1:6,6,FALSE), nrow=3, ncol=2) 
    x <- matrix(sample(1:5,15,TRUE), nrow=5, ncol=3)
    x %*% y
    
    > x %*% y
         [,1] [,2]
    [1,]   47   46
    [2,]   32   32
    [3,]   31   24
    [4,]   18   16
    [5,]   37   34
    

    感谢所有回复。您的编码教会了我很多关于 R 的工作原理以及如何为某些函数编写脚本的知识。谢谢

    【讨论】:

      猜你喜欢
      • 2019-10-08
      • 1970-01-01
      • 2018-03-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多