我想做一个扭曲的矩阵乘法。
我有这个矩阵:
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
我一直在尝试应用,扫描和循环,但我无法得到它。 谢谢你的回复。
答案 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