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)
}
The following will do it.
m1 <- setdiff(rownames(mat2), rownames(mat1))
newMat1 <- rbind(mat1, matrix(0, nrow = length(m1), ncol = ncol(mat1)))
newMat1 <- cbind(newMat1, matrix(0, nrow = nrow(newMat1), ncol = length(m1)))
rownames(newMat1) <- c(rownames(mat1), m1)
colnames(newMat1) <- c(colnames(mat1), m1)
m2 <- setdiff(rownames(mat1), rownames(mat2))
newMat2 <- rbind(mat2, matrix(0, nrow = length(m2), ncol = ncol(mat2)))
newMat2 <- cbind(newMat2, matrix(0, nrow = nrow(newMat2), ncol = length(m2)))
rownames(newMat2) <- c(rownames(mat2), m2)
colnames(newMat2) <- c(colnames(mat2), m2)
Since the code repeats, it would be possible to write a function. If this is a one time problem, there's really no reason for it, but if you have more such problems, say so.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With