R - 如何使两个邻接矩阵相互兼容

3

我有两个不同维度的邻接矩阵。我想让它们的维度兼容,这样当我将其中一个矩阵的任何一列替换为第二个矩阵的任何一列时,就不会出现以下错误信息: 错误:要替换的项目数量不是替换长度的倍数 这是我的矩阵:

> 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

为了使mat1与mat2兼容,我需要在mat1中添加2列和2行,使其变为:
> 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

这里添加了2行2列新数据(MikeDan),因为它们之前不存在于原矩阵中。请注意,新添加的行和列已经被初始化为值 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

以下是原始矩阵的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")))

编辑:

如问题所述,我想在矩阵之间替换列,但问题在于当我这样做时,列名称和行名称的不同顺序会影响索引中的值。例如:

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

这里将newMat1中的Mike列替换为newMat2中的Mike列。您可以看到,原始newMat2中的Mike-to-Mike索引为0,但在新获得的newMat1中为1,这是因为行名和列名的排序不同。

回答: 为了达到这个目的,需要进行排序,方法如下:

newMat2 <- newMat2[rownames(newMat1), colnames(newMat1)]
3个回答

4
一个简单的函数:
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)

首先,它找到聚焦矩阵 mat 和参考矩阵 ref 之间缺失的名称,然后用0将两个矩阵绑定在一起以填补缺失的名称。

> 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

另一个解决方案:

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

谢谢您的回答。请问您能指导我如何重新排序这些矩阵,使它们在行名和列名方面看起来相同吗? - Newbie
newMat2 <- newMat2[rownames(newMat1), colnames(newMat1)] - Axeman
是的,就这样。非常感谢! - Newbie
你能帮我解决这个问题吗?需要用foreach循环或parSapply替换for循环。谢谢。 - Newbie
嗨@Axeman,我想知道你是否可以看一下这个相关问题 - Rich Pauloo

2
以下将会完成它。
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)

由于代码重复,可以编写一个函数来解决这个问题。如果这只是一个一次性的问题,那么没有必要这样做,但是如果您有更多类似的问题,请告诉我们。


0

也许有点过度,但这是一个通用的解决方案:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接