Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
730 views
in Technique[技术] by (71.8m points)

matrix - R: add matrices based on row and column names

I have two matrices I want to sum based on their row and column names. The matrices will not necessarily have all rows and columns in common - some may be missing from either matrix.

For example, consider two matrices A and B:

A=                 B=
  a b c d            a c d e
v 1 1 1 0          v 0 0 0 1
w 1 1 0 1          w 0 0 1 0
x 1 0 1 1          y 0 1 0 0
y 0 1 1 1          z 1 0 0 0

Column e is missing from matrix A and column b is missing from matrix B. Row z is missing from matrix A and row x is missing from matrix B.

The summed table I'm looking for is:

Sum=
  a b  c d e
v 1 1  1 0 1
w 1 1  0 2 0
x 1 0  1 1 na
y 0 1  2 1 0
z 1 na 0 0 0

The row and column ordering in the final matrix don't matter, as long as the matrix is complete, i.e. has all the data. Missing values don't have to be "Na", but could be "0" instead.

I'm not sure if there is a way to do this that doesn't involve for loops. Any help would be much appreciated.

My solution

I managed to do this easily by converting the matrices to dataframes, binding the dataframes by row and then casting the resulting dataframe back into a matrix. This looks like it works, but maybe someone could double check or let me know if there is a better way.

library(reshape2)
A_df=as.data.frame(as.table(A))
B_df=as.data.frame(as.table(B))

merged_df=rbind(A_df,B_df)

Summed_matrix=acast(merged_df, Var1 ~ Var2, sum)

merged_df looks like this:

   Var1 Var2 Freq
1     v    a    1
2     w    a    1
3     x    a    1
4     y    a    0
5     v    b    1
6     w    b    1
etc...
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

May be you can try:

cAB <- union(colnames(A), colnames(B))
rAB <- union(rownames(A), rownames(B))

A1 <- matrix(0, ncol=length(cAB), nrow=length(rAB), dimnames=list(rAB, cAB))
B1 <- A1

indxA <- outer(rAB, cAB, FUN=paste) %in% outer(rownames(A), colnames(A), FUN=paste) 
indxB <- outer(rAB, cAB, FUN=paste) %in% outer(rownames(B), colnames(B), FUN=paste)
A1[indxA] <- A
B1[indxB] <- B

A1+B1 #because it was mentioned to have `0` as missing values
#  a b c d e
#v 1 1 1 0 1
#w 1 1 0 2 0
#x 1 0 1 1 0
#y 0 1 2 1 0
#z 1 0 0 0 0

If you want to get the NA as missing values

A1 <- matrix(NA, ncol=length(cAB), nrow=length(rAB), dimnames=list(rAB, cAB))
B1 <- A1

A1[indxA] <- A
B1[indxB] <- B

indxNA <- is.na(A1) & is.na(B1)
A1[is.na(A1)!= indxNA] <- 0
B1[is.na(B1)!= indxNA] <- 0


A1+B1
#  a  b c d  e
#v 1  1 1 0  1
#w 1  1 0 2  0
#x 1  0 1 1 NA
#y 0  1 2 1  0
#z 1 NA 0 0  0

Or using reshape2

library(reshape2)
acast(rbind(melt(A), melt(B)), Var1~Var2, sum) #Inspired from the OP's idea
#  a b c d e
#v 1 1 1 0 1
#w 1 1 0 2 0
#x 1 0 1 1 0
#y 0 1 2 1 0
#z 1 0 0 0 0

data

A <- structure(c(1L, 1L, 1L, 0L, 1L, 1L, 0L, 1L, 1L, 0L, 1L, 1L, 0L, 
1L, 1L, 1L), .Dim = c(4L, 4L), .Dimnames = list(c("v", "w", "x", 
"y"), c("a", "b", "c", "d")))

B <- structure(c(0L, 0L, 0L, 1L, 0L, 0L, 1L, 0L, 0L, 1L, 0L, 0L, 1L, 
0L, 0L, 0L), .Dim = c(4L, 4L), .Dimnames = list(c("v", "w", "y", 
"z"), c("a", "c", "d", "e")))

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...