I have 2 adjacency matrices with different dimesnsions. I want to make their dimensions compatible so that when I replace any column of one matrix from any column of second matrix then I don't get the following error message: Error: number of items to replace is not a multiple of replacement length Here are my matrices:
> mat1
Tommy Roy Addy Sam
Tommy 0 1 0 -1
Roy -1 -1 1 0
Addy 1 0 -1 0
Sam 0 0 -1 1
> mat2
Mike Roy Addy Sam Dan
Mike 0 1 0 -1 0
Roy -1 -1 1 0 1
Addy 1 0 -1 0 -1
Sam 0 0 -1 1 0
Dan 1 0 0 -1 1
To make the mat1 compatible to mat2 I have to add 2 columns and 2 rows in mat1, so that it become:
> newMat1
Tommy Roy Addy Sam Mike Dan
Tommy 0 1 0 -1 0 0
Roy -1 -1 1 0 0 0
Addy 1 0 -1 0 0 0
Sam 0 0 -1 1 0 0
Mike 0 0 0 0 0 0
Dan 0 0 0 0 0 0
Here 2 new column and rows have been added (Mike
and Dan
) as they were not there before but were part of the second matrix. Please notice that newly added rows and columns have been initialized with 0
value. Similarly newMat2 will become:
> newMat2
Mike Roy Addy Sam Dan Tommy
Mike 0 1 0 -1 0 0
Roy -1 -1 1 0 1 0
Addy 1 0 -1 0 -1 0
Sam 0 0 -1 1 0 0
Dan 1 0 0 -1 1 0
Tommy 0 0 0 0 0 0
Here are the original matrices dput:
> dput(mat1)
structure(c(0L, -1L, 1L, 0L, 1L, -1L, 0L, 0L, 0L, 1L, -1L, -1L,
-1L, 0L, 0L, 1L), .Dim = c(4L, 4L), .Dimnames = list(c("Tommy",
"Roy", "Addy", "Sam"), c("Tommy", "Roy", "Addy", "Sam")))
> dput(mat2)
structure(c(0L, -1L, 1L, 0L, 1L, 1L, -1L, 0L, 0L, 0L, 0L, 1L,
-1L, -1L, 0L, -1L, 0L, 0L, 1L, -1L, 0L, 1L, -1L, 0L, 1L), .Dim = c(5L,
5L), .Dimnames = list(c("Mike", "Roy", "Addy", "Sam", "Dan"),
c("Mike", "Roy", "Addy", "Sam", "Dan")))
EDIT:
As mentioned in question, I want to later replace the the columns between the matrices and problem is that when I do this the different ordering of colnames and rownames affect the values in the indices. for example:
Change <- c("Mike", "Dan")
for(i in 1:length(Change)){
ifelse(Change[i] %in% colnames(newMat1), newMat1[,Change[i]] <- newMat2[,Change[i]], newMat1[,Change[i]][newMat1[,Change[i]] == 1] <- 0)}
newMat1
Tommy Roy Addy Sam Mike Dan
Tommy 0 1 0 -1 0 0
Roy -1 -1 1 0 -1 1
Addy 1 0 -1 0 1 -1
Sam 0 0 -1 1 0 0
Mike 0 0 0 0 1 1
Dan 0 0 0 0 0 0
Here the Mike column in newMat1 has been replaced by Mike column in newMat2. As you can see that index Mike-to-Mike is 0 in original newMat2 but it is 1 in freshly obtained newMat1, and that is because of ordering of rownames and colnames is different.
Answer: For this purpose ordering was required and it was done by:
newMat2 <- newMat2[rownames(newMat1), colnames(newMat1)]
A simple function:
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)
}
newMat1 <- complete_matrix(mat1, mat2)
newMat2 <- complete_matrix(mat2, mat1)
It first finds the missing names between the focal matrix mat
and the reference matrix ref
, then binds two matrices with 0s for the missing names..
> newMat1
Tommy Roy Addy Sam Mike Dan
Tommy 0 1 0 -1 0 0
Roy -1 -1 1 0 0 0
Addy 1 0 -1 0 0 0
Sam 0 0 -1 1 0 0
Mike 0 0 0 0 0 0
Dan 0 0 0 0 0 0
> newMat2
Mike Roy Addy Sam Dan Tommy
Mike 0 1 0 -1 0 0
Roy -1 -1 1 0 1 0
Addy 1 0 -1 0 -1 0
Sam 0 0 -1 1 0 0
Dan 1 0 0 -1 1 0
Tommy 0 0 0 0 0 0
Another solution:
complete_matrix2 <- function(mat, ref) {
nam <- union(rownames(ref), rownames(mat))
out <- matrix(0, length(nam), length(nam), dimnames = list(nam, nam))
out[rownames(mat), colnames(mat)] <- mat
return(mat)
}