R - 如何使 2 个邻接矩阵相互兼容
R - How to make 2 adjacency matrices compatible to eachother
我有 2 个不同维度的邻接矩阵。我想让它们的尺寸兼容,这样当我从第二个矩阵的任何列替换一个矩阵的任何列时,我就不会收到以下错误消息:
错误:要替换的项目数不是替换长度的倍数
这是我的矩阵:
> 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 个新的列和行(Mike
和 Dan
),因为它们以前不存在,但属于第二个矩阵的一部分。请注意,新添加的行和列已使用 0
值进行了初始化。同样 newMat2 将变为:
> 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")))
编辑:
如问题所述,我想稍后替换矩阵之间的列,问题是当我这样做时,colnames 和 rownames 的不同排序会影响索引中的值。例如:
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 列替换。如您所见,索引 Mike-to-Mike 在原始 newMat2 中为 0,但在新获得的 newMat1 中为 1,这是因为 rownames 和 colnames 的顺序不同。
回答:为此需要订购,并由以下人员完成:
newMat2 <- newMat2[rownames(newMat1), colnames(newMat1)]
下面会做的
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)
既然代码重复了,写一个函数就可以了。如果这是一次性问题,那真的没有理由,但如果你有更多这样的问题,那就说吧。
一个简单的函数:
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)
}
可能有点矫枉过正,但这是一个通用的解决方案:
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
我有 2 个不同维度的邻接矩阵。我想让它们的尺寸兼容,这样当我从第二个矩阵的任何列替换一个矩阵的任何列时,我就不会收到以下错误消息: 错误:要替换的项目数不是替换长度的倍数 这是我的矩阵:
> 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 个新的列和行(Mike
和 Dan
),因为它们以前不存在,但属于第二个矩阵的一部分。请注意,新添加的行和列已使用 0
值进行了初始化。同样 newMat2 将变为:
> 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")))
编辑:
如问题所述,我想稍后替换矩阵之间的列,问题是当我这样做时,colnames 和 rownames 的不同排序会影响索引中的值。例如:
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 列替换。如您所见,索引 Mike-to-Mike 在原始 newMat2 中为 0,但在新获得的 newMat1 中为 1,这是因为 rownames 和 colnames 的顺序不同。
回答:为此需要订购,并由以下人员完成:
newMat2 <- newMat2[rownames(newMat1), colnames(newMat1)]
下面会做的
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)
既然代码重复了,写一个函数就可以了。如果这是一次性问题,那真的没有理由,但如果你有更多这样的问题,那就说吧。
一个简单的函数:
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)
}
可能有点矫枉过正,但这是一个通用的解决方案:
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