How to aggregate matrices which have different dimensions? [R]

不羁的心 提交于 2021-01-28 05:10:19

问题


I have a few hundred thousands of matrices in a list which should be aggregated by group identifier. For instance, there are two matrices with different dimentions.

a <- matrix(c(1:12),nrow=3,ncol=4,dimnames=list(c(0:2),c(0:3)))
b <- matrix(c(1:6),nrow=2,ncol=3,dimnames=list(c(0:1),c(0:2)))

> a
  0 1 2  3
0 1 4 7 10
1 2 5 8 11
2 3 6 9 12
> b
  0 1 2
0 1 3 5
1 2 4 6

Do you know how to aggregate those matrices to obtain following matrix in a simple way?

c <- a + b
> c
   0  1  2  3
0  2  7 12 10
1  4  9 14 11
2  3  6  9 12

It may not be such a difficult question, however I could not find the solution.
Row and column names start from 0 which sequentially step-up by 1 but maximum number varies based on each element. Unmatched dimentions in smaller matrices can be padded by 0.
I suppose I can aggregate them by group but cannot aggregate matrices with different dimentions.


回答1:


Here are some alternative solutions:

1) Convert each to long form giving both and then use tapply to aggregate and convert back to wide form:

both <- rbind(as.data.frame.table(a), as.data.frame.table(b))
tapply(both[[3]], both[-3], sum, default = 0)

giving:

    Var2
Var1 0 1  2  3
   0 2 7 12 10
   1 4 9 14 11
   2 3 6  9 12

2) This creates a matrix zero having the shape of the result and then defines a function upleft which inserts its first argument into the upper left of zero. Finally we add them together.

upleft <- function(x, zero) replace(zero, cbind(c(row(x)), c(col(x))), x)
zero <- array(0, pmax(dim(a), dim(b)))
upleft(a, zero) + upleft(b, zero)

giving:

     [,1] [,2] [,3] [,4]
[1,]    2    7   12   10
[2,]    4    9   14   11
[3,]    3    6    9   12



回答2:


Here's a function which takes in two matrices and pads them with 0's to make their dimensions the same. Then it sums them. This can be used with Reduce to sum many together in one operation.

First, get the max number of rows and the max number of columns of the two matrices. Then, a matrix of 0's is created with these max dimensions. Then, only the sub-matrix that matches each input is populated. The matrices are summed and returned.

sum_ragged_matrix = function(m1,m2){
  m1r = nrow(m1r)
  m2r = nrow(m2r)

  m1c = ncol(m1c)
  n2c = ncol(m2c)

  max_rows = max(c(m1r,m2r))
  max_cols = max(c(m1c,m2c))
  t1 = matrix(0,nrow = max_rows,ncol = max_cols)
  t2 = t1
  t1[1:m1r,1:m1c] = m1
  t2[1:m2r,1:m2c] = m2
  return(t1+t2)
}

a = matrix(c(1:12),nrow=3,ncol=4,dimnames=list(c(0:2),c(0:3)))
b = matrix(c(1:6),nrow=2,ncol=3,dimnames=list(c(0:1),c(0:2)))
c = matrix(c(1:4),nrow=2,ncol=2,dimnames=list(c(0:1),c(0:1)))

Reduce(sum_ragged_matrix,list(a=a,b=b,c=c),init=matrix(0,nrow=1,ncol=1))



回答3:


You could use this function that takes any two matrices, adjusts the number of rows and columns, pads them with 0s, and then adds them up.

sum_mat = function(a, b){
    temp = matrix(data = 0, nrow = max(nrow(a), nrow(b)), ncol = max(ncol(a), ncol(b)))
    temp_a = temp
    temp_a[1:nrow(a), 1:ncol(a)] = a
    temp_b = temp
    temp_b[1:nrow(b), 1:ncol(b)] = b
    temp_a + temp_b
}


> a
  0 1 2  3
0 1 4 7 10
1 2 5 8 11
2 3 6 9 12

> b
  0 1 2
0 1 3 5
1 2 4 6

c = sum_mat(a, b)

> c
   0  1  2  3
0  2  7 12 10
1  4  9 14 11
2  3  6  9 12


来源:https://stackoverflow.com/questions/51383805/how-to-aggregate-matrices-which-have-different-dimensions-r

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!