R - How to make 2 adjacency matrices compatible to eachother

跟風遠走 提交于 2020-01-04 05:04:34

问题


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)]

回答1:


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)
}



回答2:


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.




回答3:


Maybe a bit overkill, but here's a general solution:

library(tidyverse)
imap_dfr(list(mat1,mat2),~ .x %>% 
          as.data.frame(stringsAsFactors=F) %>%
          mutate(v = row.names(.),mat = .y) %>%
          gather(h,value,-(ncol(.)+c(0,-1))))  %>%
  right_join(expand(.,v,h,mat)) %>%
  replace_na(list(value=0)) %>%
  split(.$mat) %>%
  map(. %>%
        spread(h,value,0) %>%
        `row.names<-`(.$v) %>%
        select(-v,-mat) %>%
        as.matrix)

$`1`
      Addy Dan Mike Roy Sam Tommy
Addy    -1   0    0   0   0     1
Dan      0   0    0   0   0     0
Mike     0   0    0   0   0     0
Roy      1   0    0  -1   0    -1
Sam     -1   0    0   0   1     0
Tommy    0   0    0   1  -1     0

$`2`
      Addy Dan Mike Roy Sam Tommy
Addy    -1  -1    1   0   0     0
Dan      0   1    1   0  -1     0
Mike     0   0    0   1  -1     0
Roy      1   1   -1  -1   0     0
Sam     -1   0    0   0   1     0
Tommy    0   0    0   0   0     0


来源:https://stackoverflow.com/questions/46295687/r-how-to-make-2-adjacency-matrices-compatible-to-eachother

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