如何修改矩阵乘法以仅将R中的正值或负值相加

时间:2017-04-14 20:22:11

标签: r matrix cross-product

我想做一个扭曲的矩阵乘法。

我有这个矩阵:

A <- matrix(c(1,-1,-1,0,-1,0,1,0,0,1,0,0,0,1,-1,1,-1,0,0,-1,1,0,1,0,1,-1,-1,1,-1,1), nrow = 6, ncol = 5)

A
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    1    0    0    1
[2,]   -1    0    1   -1   -1
[3,]   -1    0   -1    1   -1
[4,]    0    1    1    0    1
[5,]   -1    0   -1    1   -1
[6,]    0    0    0    0    1

我想得到两个不同的矩阵。第一个矩阵是:

C
     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    0    0    0    2    0    1
[2,]    0    0    2    1    2    0
[3,]    0    2    0    0    4    0
[4,]    2    1    0    0    0    1
[5,]    0    2    4    0    0    0
[6,]    1    0    0    1    0    0

这个“收敛矩阵”类似于A的转置乘法(在R中就像这个A%*%t(A)),但有一点点扭曲,在得到每个单元格的总和中我只想要总和积极的价值观。例如,对于单元格C23,常规和将是:

  

( - 1)( - 1)+(0)(0)+(1)( - 1)+( - 1)(1)+( - 1)( - 1)= 0

,但我只想要积极产品的总和,在本例中第一个[(-1)( - 1)]和最后一个[(-1)( - 1)]得到2。

第二个矩阵是:

D
     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    0    2    2    0    2    0
[2,]    2    0    2    1    2    1
[3,]    2    2    0    2    0    1
[4,]    0    1    2    0    2    0
[5,]    2    2    0    2    0    1
[6,]    0    1    1    0    1    0

这个“发散矩阵”与前一个相似,区别在于我只想求负值的绝对值。例如,对于单元格D23,常规总和将是:

  

( - 1)( - 1)+(0)(0)+(1)( - 1)+( - 1)(1)+( - 1)( - 1)= 0

,但我只想要负产品的绝对值之和,在本例中第三个abs [(1)( - 1)]和第四个abs [( - 1)( - 1)]得到2

我一直在尝试应用,扫描和循环,但我无法得到它。 谢谢你的回复。

3 个答案:

答案 0 :(得分:1)

它的效率会明显降低,但您可以将矩阵分解为行向量列表,这些行向量更易于计算。使用purrr,这对列表很方便,

library(purrr)

A <- matrix(c(1,-1,-1,0,-1,0,1,0,0,1,0,0,0,1,-1,1,-1,0,0,-1,1,0,1,0,1,-1,-1,1,-1,1), 
            nrow = 6, ncol = 5)

C <- seq(nrow(A)) %>%    # generate a sequence of row indices
    map(~A[.x, ]) %>%   # subset matrix into a list of rows
    cross2(., .) %>%    # do a Cartesian join to get pairs of rows
    # calculate products, then subset before summing. Simplify to vector
    map_dbl(~{ij <- .x[[1]] * .x[[2]]; sum(ij[ij >= 0])}) %>% 
    matrix(nrow(A))    # reassemble to matrix

C
#>      [,1] [,2] [,3] [,4] [,5] [,6]
#> [1,]    3    0    0    2    0    1
#> [2,]    0    4    2    1    2    0
#> [3,]    0    2    4    0    4    0
#> [4,]    2    1    0    3    0    1
#> [5,]    0    2    4    0    4    0
#> [6,]    1    0    0    1    0    1

# same except subsetting and `-` to make negatives positive
D <- seq(nrow(A)) %>% 
    map(~A[.x, ]) %>%
    cross2(., .) %>% 
    map_dbl(~{ij <- .x[[1]] * .x[[2]]; sum(-ij[ij <= 0])}) %>% 
    matrix(nrow(A))

D
#>      [,1] [,2] [,3] [,4] [,5] [,6]
#> [1,]    0    2    2    0    2    0
#> [2,]    2    0    2    1    2    1
#> [3,]    2    2    0    2    0    1
#> [4,]    0    1    2    0    2    0
#> [5,]    2    2    0    2    0    1
#> [6,]    0    1    1    0    1    0

答案 1 :(得分:1)

这是基础R的尝试。所以基本上你遵循矩阵交叉产品方法但是你试图手动管理sum步骤:

f <- function(A, convergence=TRUE){
    sapply(seq_len(nrow(A)), function(i) {
        r <- t(matrix(A[i,],ncol(A),nrow(A)))*A
        if(convergence)
            r[r<0] <- 0
        else
            r[r>0] <- 0
        rowSums(abs(r))
    })
}

> f(A, convergence = TRUE)

     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    3    0    0    2    0    1
[2,]    0    4    2    1    2    0
[3,]    0    2    4    0    4    0
[4,]    2    1    0    3    0    1
[5,]    0    2    4    0    4    0
[6,]    1    0    0    1    0    1

> f(A, convergence = FALSE)

     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    0    2    2    0    2    0
[2,]    2    0    2    1    2    1
[3,]    2    2    0    2    0    1
[4,]    0    1    2    0    2    0
[5,]    2    2    0    2    0    1
[6,]    0    1    1    0    1    0

答案 2 :(得分:1)

另一种观点:

D <- A
D[D<0] = -1i*D[D<0]
D <- Im(tcrossprod(D))

C <- tcrossprod(A) + D
问题中定义了

A。 输出:

> D
     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    0    2    2    0    2    0
[2,]    2    0    2    1    2    1
[3,]    2    2    0    2    0    1
[4,]    0    1    2    0    2    0
[5,]    2    2    0    2    0    1
[6,]    0    1    1    0    1    0
> C
     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    3    0    0    2    0    1
[2,]    0    4    2    1    2    0
[3,]    0    2    4    0    4    0
[4,]    2    1    0    3    0    1
[5,]    0    2    4    0    4    0
[6,]    1    0    0    1    0    1