How to make the original matrix defined by the values of its subset matrix?

Hello All,

I would like to combine two data matrices. One is the reference matrix, and the second is the subset of the reference matrix. I want the reference matrix to contain all values of the subset matrix only and the rest of the matrix to be zero.
For example, I have seen a few solutions in the link below.
https://stackoverflow.com/questions/55735530/join-two-adjacency-matrices-and-retain-values

However, I need some one to suggest to me if there is another elegant way to do it.
The codes are below.
best,
ADR

ref = structure(c(0L, 1L, 1L, 0L, 1L, 1L, 1L, 0L, 0L, 0L, 0L, 1L,0L,0L,0L, 0L, 0L, 1L,0L,0L,1L,0L,0L,
                  1L, 1L, 0L, 1L, 0L, 0L, 1L, 1L, 0L, 1L, 1L, 0L, 1L), .Dim = c(6L, 6L), 
                .Dimnames = list(c("Mike", "Roy", "Addy", "Sam", "Dan","Tommy"), 
                                 c("Mike", "Roy", "Addy", "Sam", "Dan","Tommy")))
mat = ref[1:3,1:3]

complete_matrix <- function(mat, ref) {
  dif <- setdiff(rownames(ref), rownames(mat))
  mat <- rbind(mat, matrix(0, length(dif), ncol(mat), dimnames = list(dif, NULL)))
  mat <- cbind(mat, matrix(0, nrow(mat), length(dif), dimnames = list(NULL, dif)))
  return(mat)
}
complete_matrix(mat, ref)

elegance is a somewhat subjective and certainly non-technical term; perhaps you could say why you feel the solution you have is so inelegant to the degree that you would wish to surpass it ? I have to say from my perspective it seems rather elegant to me.

2 Likes

Based on your ask, the only correction I'd make is replacing the <- with = within the function. This would better align with best-practices in R. But what you have works perfectly fine.
e.g. (<- for assignment, = for equivalence, == for test)

However a more elegant solution to me would be the following.

# Subset [mat]
ref[1:2, 1:2] # Top Left

# Based on subset; the following are the remaining 3 quadrants. 
ref[1:2, 3:6] # Top Right
ref[3:6, 1:2] # Bottom Left
ref[3:6, 3:6] # Bottom Right

# Modify existing set [ref] to reflect [mat]
ref[1:2, 3:6] <- 0 # Top Right
ref[3:6, 1:2] <- 0 # Bottom Left
ref[3:6, 3:6] <- 0 # Bottom Right

Especially in communicating information to others that may use or read your code.

Or if your intent is to utilize a function, I'd like your thoughts on the following.

fun_mat <- function(set, r, c){
 set[r, -c] = 0  # 2nd quad.
 set[-r, c] = 0  # 3rd quad.
 set[-r, -c] = 0 # 4th quad.
 return(set)
}

fun_mat(ref, c(1, 2), c(1, 2))
> fun_mat(ref, c(1, 2), c(1, 2))
      Mike Roy Addy Sam Dan Tommy
Mike     0   1    0   0   0     0
Roy      1   0    0   0   0     0
Addy     0   0    0   0   0     0
Sam      0   0    0   0   0     0
Dan      0   0    0   0   0     0
Tommy    0   0    0   0   0     0

How about with matrix indexing using the row/column names?

comp_mat <- function(mat, ref) {
    ref[] <- 0
    ref[as.matrix(expand.grid(dimnames(mat)))] <- mat
    ref
}
identical( comp_mat(mat, ref), complete_matrix(mat, ref) )
#[1] TRUE

@thelatemail

The solution works, however, if you run the code below and compare the result using the identical function, it returns FALSE. I know the second matrix is subsetted at different indexes.
Best,
Amare

ref = matrix(rnorm(100), nrow = 10)
mat = matrix(rnorm(25), nrow = 5)
rownames(ref) <- colnames(ref) <- letters[1:10]
rownames(mat) <- colnames(mat) <- c("a","b","h","i","j")
identical( comp_mat(mat, ref), complete_matrix(mat, ref) )
#[1] FALSE

How about this:

ref = structure(c(0L, 1L, 1L, 0L, 1L, 1L, 1L, 0L, 0L, 0L, 0L, 1L,0L,0L,0L, 0L, 0L, 1L,0L,0L,1L,0L,0L,
                  1L, 1L, 0L, 1L, 0L, 0L, 1L, 1L, 0L, 1L, 1L, 0L, 1L), .Dim = c(6L, 6L), 
                .Dimnames = list(c("Mike", "Roy", "Addy", "Sam", "Dan","Tommy"), 
                                 c("Mike", "Roy", "Addy", "Sam", "Dan","Tommy")))
mat = ref[1:3,1:3]

ref[] <- 0L
ref[rownames(mat), colnames(mat)] <- mat