如何select基于关系的(邻接)矩阵中的子矩阵,在R
how to select submatrix in a (adjacency) matrix based on ties, in R
我有一个矩阵,表示不同工作之间的流动性:
jobdat <- matrix(c(
295, 20, 0, 0, 0, 5, 7,
45, 3309, 15, 0, 0, 0, 3,
23, 221, 2029, 5, 0, 0, 0,
0, 0, 10, 100, 8, 0, 3,
0, 0, 0, 0, 109, 4, 4,
0, 0, 0, 0, 4, 375, 38,
0, 18, 0, 0, 4, 26, 260),
nrow = 7, ncol = 7, byrow = TRUE,
dimnames = list(c("job 1","job 2","job 3","job 4","job 5","job 6","job 7"),
c("job 1","job 2","job 3","job 4","job 5","job 6","job 7")))
这在社交网络分析中被视为定向加权邻接矩阵。
网络的方向是从行到列:因此移动性被定义为从工作行到工作列。对角线是有意义的,因为可以在另一家公司换到同一份工作。
对于我的部分分析,我想要 select 一个由作业 1、作业 5 和作业 7 组成的子矩阵:
work.list <- c(1,5,7)
jobpick_wrong <- jobdat[work.list,work.list]
然而,这只给出了这三个工作之间的直接联系。我需要的是:
jobpick_right <- matrix(c(
295, 20, 0, 5, 7,
45, 3309, 0, 0, 3,
0, 0, 109, 4, 4,
0, 0, 4, 375, 38,
0, 18, 4, 26, 260),
nrow = 5, ncol = 5, byrow = TRUE,
dimnames = list(c("job 1","job 2","job 5","job 6","job 7"),
c("job 1","job 2","job 5","job 6","job 7")))
这里,工作 2 和 6 也包括在内,因为这两个工作也与工作 1、5 或 7 有直接联系。而工作 3 和 4 被排除在外,因为它们与工作 1 没有任何联系, 5 或 7.
我不知道该怎么做。也许我必须将它转换成 igraph 对象才能到达任何地方?
net <- graph.adjacency(jobdat, mode = "directed", weighted = TRUE)
然后也许使用 ego/neighborhood-function,也来自 igraph 包?但是我真的不确定如何。或者这是最好的解决方法。
感谢您的宝贵时间,
Emil Begtrup-Bright
扩充问题:
aichao 的回答非常适合所问的问题,尽管事实证明还需要一个步骤。当创建 work.list 时,其中包含与三个 "jobs of interest" 相关的作业,本例中为作业 1、5、7。然后,对于真实数据,混乱的数量使另一个步骤变得可取:只保留与三个感兴趣的工作之间的 直接 联系,而其他工作之间的联系设置为零.
上面的数据并没有很好地描述这一点,所以我创建了上面的一个非常版本来证明这一点:
jobdat <- matrix(c(
1, 0, 1, 0, 0, 0, 0,
1, 1, 1, 0, 0, 0, 0,
1, 1, 1, 0, 0, 0, 0,
0, 0, 0, 1, 0, 0, 0,
0, 0, 0, 0, 1, 0, 0,
0, 0, 0, 0, 0, 1, 0,
0, 0, 0, 0, 0, 0, 1
),
nrow = 7, ncol = 7, byrow = TRUE,
dimnames = list(c("job 1","job 2","job 3","job 4","job 5","job 6","job 7"),
c("job 1","job 2","job 3","job 4","job 5","job 6","job 7")))
使用aichaos解决方案:
work.list <- sort(unique(unlist(lapply(work.list, function(x) which(jobdat[x,] != 0)))))
然后我们得到这个:
jobdat[work.list,work.list]
# job 1 job 2 job 3 job 5 job 7
# job 1 1 0 1 0 0
# job 2 1 1 1 0 0
# job 3 1 1 1 0 0
# job 5 0 0 0 1 0
# job 7 0 0 0 0 1
但是,工作 2 和工作 3 之间的联系无关紧要,只会掩盖利益联系。
jobdat.result <- matrix(c(
1, 0, 1, 0, 0,
1, 1, 0, 0, 0,
1, 0, 1, 0, 0,
0, 0, 0, 1, 0,
0, 0, 0, 0, 1
),
nrow = 5, ncol = 5, byrow = TRUE,
dimnames = list(c("job 1","job 2","job 3","job 5","job 7"),
c("job 1","job 2","job 3","job 5","job 7")))
在 job.dat.result 中,作业 3 和作业 2 之间的联系已被删除,包括行向和列向,但保留了这两个作业和感兴趣的三个作业之间的联系。理想情况下,应该可以选择作业 2 和作业 3 的对角线是否也应为零。但最有可能的是,对于所有作业,我会将对角线设置为零,因此这不是必需的。但这很好,如果没有别的,那么我可以在更高层次上理解它的逻辑。
除其他外,我想要实现的是像这样的圆图:
所以领带数量的简单性很重要。图表转载如下:
library(circlize)
segmentcircle <- jobdat
diag(segmentcircle) <- 0
df.c <- get.data.frame(graph.adjacency(segmentcircle,weighted=TRUE))
colour <- brewer.pal(ncol(segmentcircle),"Set1")
chordDiagram(x = df.c,
grid.col = colour,
transparency = 0.2,
directional = 1, symmetric=FALSE,
direction.type = c("arrows", "diffHeight"), diffHeight = -0.065,
link.arr.type = "big.arrow",
# self.link=1
link.sort = TRUE, link.largest.ontop = TRUE,
link.border="black",
# link.lwd = 2,
# link.lty = 2
)
假设你的有向图是从行到列,你可以做的是增加你的 work.list
与那些连接(元素!=0)到 [=20= 中的每一行的列].您可以通过以下方式做到这一点:
work.list <- sort(unique(unlist(lapply(work.list, function(x) which(jobdat[x,] != 0)))))
使用 unique
仅保留唯一的列组合,并使用 sort
以便这些列按其索引排序。那么:
jobdat[work.list,work.list]
## job 1 job 2 job 5 job 6 job 7
##job 1 295 20 0 5 7
##job 2 45 3309 0 0 3
##job 5 0 0 109 4 4
##job 6 0 0 4 375 38
##job 7 0 18 4 26 260
相反,如果您的有向图是从列到行:
work.list <- sort(unique(unlist(lapply(work.list, function(x) which(jobdat[,x] != 0)))))
已更新扩充问题:
随着新 jobdat
:
jobdat <- matrix(c(
1, 0, 1, 0, 0, 0, 0,
1, 1, 1, 0, 0, 0, 0,
1, 1, 1, 0, 0, 0, 0,
0, 0, 0, 1, 0, 0, 0,
0, 0, 0, 0, 1, 0, 0,
0, 0, 0, 0, 0, 1, 0,
0, 0, 0, 0, 0, 0, 1
),
nrow = 7, ncol = 7, byrow = TRUE,
dimnames = list(c("job 1","job 2","job 3","job 4","job 5","job 6","job 7"),
c("job 1","job 2","job 3","job 4","job 5","job 6","job 7")))
和work.list
中的相关职位列表:
work.list <- c(1,5,7)
计算扩充工作列表 aug.work.list
作为直接转到 work.list
中相关工作的工作集合。这将包括工作 2 和 3。请注意,我们在这里使用 which(jobdat[,x] != 0)
而不是 which(jobdat[x,] != 0)
来标识连接到 [= 中的相关工作 x
的工作(相关或不相关) 20=].
aug.work.list <- sort(unique(unlist(lapply(work.list, function(x) which(jobdat[,x] != 0)))))
##[1] 1 2 3 5 7
这导致:
jobdat.result <- jobdat[aug.work.list, aug.work.list]
## job 1 job 2 job 3 job 5 job 7
##job 1 1 0 1 0 0
##job 2 1 1 1 0 0
##job 3 1 1 1 0 0
##job 5 0 0 0 1 0
##job 7 0 0 0 0 1
现在,要去除不相关作业之间的联系,首先在 jobdat.result
中找到这些不相关作业的索引,这些索引是 aug.work.list
中不在 work.list
中的元素的索引
irrelevant.job.indices <- which(!(aug.work.list %in% work.list))
##[1] 2 3
请注意,这些不是不相关职位的职位编号,而是 jobdat.result
中对应于不相关职位编号的(行和列)索引。
在这种情况下,它们恰好对应于工作编号本身。
删除连接需要将 irrelevant.job.indices
索引的 jobdat.result
的子矩阵的非对角线设置为 0
。为此:
## first, keep diagonal values for irrelevant.job.indices
dvals <- diag(jobdat.result)[irrelevant.job.indices]
## set sub-matrix to zero (this will also set diagnal elements to zero)
jobdat.result[irrelevant.job.indices,irrelevant.job.indices] <- 0
## replace diagonal elements
diag(jobdat.result)[irrelevant.job.indices] <- dvals
结果是:
jobdat.result
## job 1 job 2 job 3 job 5 job 7
##job 1 1 0 1 0 0
##job 2 1 1 0 0 0
##job 3 1 0 1 0 0
##job 5 0 0 0 1 0
##job 7 0 0 0 0 1
我有一个矩阵,表示不同工作之间的流动性:
jobdat <- matrix(c(
295, 20, 0, 0, 0, 5, 7,
45, 3309, 15, 0, 0, 0, 3,
23, 221, 2029, 5, 0, 0, 0,
0, 0, 10, 100, 8, 0, 3,
0, 0, 0, 0, 109, 4, 4,
0, 0, 0, 0, 4, 375, 38,
0, 18, 0, 0, 4, 26, 260),
nrow = 7, ncol = 7, byrow = TRUE,
dimnames = list(c("job 1","job 2","job 3","job 4","job 5","job 6","job 7"),
c("job 1","job 2","job 3","job 4","job 5","job 6","job 7")))
这在社交网络分析中被视为定向加权邻接矩阵。 网络的方向是从行到列:因此移动性被定义为从工作行到工作列。对角线是有意义的,因为可以在另一家公司换到同一份工作。
对于我的部分分析,我想要 select 一个由作业 1、作业 5 和作业 7 组成的子矩阵:
work.list <- c(1,5,7)
jobpick_wrong <- jobdat[work.list,work.list]
然而,这只给出了这三个工作之间的直接联系。我需要的是:
jobpick_right <- matrix(c(
295, 20, 0, 5, 7,
45, 3309, 0, 0, 3,
0, 0, 109, 4, 4,
0, 0, 4, 375, 38,
0, 18, 4, 26, 260),
nrow = 5, ncol = 5, byrow = TRUE,
dimnames = list(c("job 1","job 2","job 5","job 6","job 7"),
c("job 1","job 2","job 5","job 6","job 7")))
这里,工作 2 和 6 也包括在内,因为这两个工作也与工作 1、5 或 7 有直接联系。而工作 3 和 4 被排除在外,因为它们与工作 1 没有任何联系, 5 或 7.
我不知道该怎么做。也许我必须将它转换成 igraph 对象才能到达任何地方?
net <- graph.adjacency(jobdat, mode = "directed", weighted = TRUE)
然后也许使用 ego/neighborhood-function,也来自 igraph 包?但是我真的不确定如何。或者这是最好的解决方法。
感谢您的宝贵时间,
Emil Begtrup-Bright
扩充问题:
aichao 的回答非常适合所问的问题,尽管事实证明还需要一个步骤。当创建 work.list 时,其中包含与三个 "jobs of interest" 相关的作业,本例中为作业 1、5、7。然后,对于真实数据,混乱的数量使另一个步骤变得可取:只保留与三个感兴趣的工作之间的 直接 联系,而其他工作之间的联系设置为零.
上面的数据并没有很好地描述这一点,所以我创建了上面的一个非常版本来证明这一点:
jobdat <- matrix(c(
1, 0, 1, 0, 0, 0, 0,
1, 1, 1, 0, 0, 0, 0,
1, 1, 1, 0, 0, 0, 0,
0, 0, 0, 1, 0, 0, 0,
0, 0, 0, 0, 1, 0, 0,
0, 0, 0, 0, 0, 1, 0,
0, 0, 0, 0, 0, 0, 1
),
nrow = 7, ncol = 7, byrow = TRUE,
dimnames = list(c("job 1","job 2","job 3","job 4","job 5","job 6","job 7"),
c("job 1","job 2","job 3","job 4","job 5","job 6","job 7")))
使用aichaos解决方案:
work.list <- sort(unique(unlist(lapply(work.list, function(x) which(jobdat[x,] != 0)))))
然后我们得到这个:
jobdat[work.list,work.list]
# job 1 job 2 job 3 job 5 job 7
# job 1 1 0 1 0 0
# job 2 1 1 1 0 0
# job 3 1 1 1 0 0
# job 5 0 0 0 1 0
# job 7 0 0 0 0 1
但是,工作 2 和工作 3 之间的联系无关紧要,只会掩盖利益联系。
jobdat.result <- matrix(c(
1, 0, 1, 0, 0,
1, 1, 0, 0, 0,
1, 0, 1, 0, 0,
0, 0, 0, 1, 0,
0, 0, 0, 0, 1
),
nrow = 5, ncol = 5, byrow = TRUE,
dimnames = list(c("job 1","job 2","job 3","job 5","job 7"),
c("job 1","job 2","job 3","job 5","job 7")))
在 job.dat.result 中,作业 3 和作业 2 之间的联系已被删除,包括行向和列向,但保留了这两个作业和感兴趣的三个作业之间的联系。理想情况下,应该可以选择作业 2 和作业 3 的对角线是否也应为零。但最有可能的是,对于所有作业,我会将对角线设置为零,因此这不是必需的。但这很好,如果没有别的,那么我可以在更高层次上理解它的逻辑。
除其他外,我想要实现的是像这样的圆图:
所以领带数量的简单性很重要。图表转载如下:
library(circlize)
segmentcircle <- jobdat
diag(segmentcircle) <- 0
df.c <- get.data.frame(graph.adjacency(segmentcircle,weighted=TRUE))
colour <- brewer.pal(ncol(segmentcircle),"Set1")
chordDiagram(x = df.c,
grid.col = colour,
transparency = 0.2,
directional = 1, symmetric=FALSE,
direction.type = c("arrows", "diffHeight"), diffHeight = -0.065,
link.arr.type = "big.arrow",
# self.link=1
link.sort = TRUE, link.largest.ontop = TRUE,
link.border="black",
# link.lwd = 2,
# link.lty = 2
)
假设你的有向图是从行到列,你可以做的是增加你的 work.list
与那些连接(元素!=0)到 [=20= 中的每一行的列].您可以通过以下方式做到这一点:
work.list <- sort(unique(unlist(lapply(work.list, function(x) which(jobdat[x,] != 0)))))
使用 unique
仅保留唯一的列组合,并使用 sort
以便这些列按其索引排序。那么:
jobdat[work.list,work.list]
## job 1 job 2 job 5 job 6 job 7
##job 1 295 20 0 5 7
##job 2 45 3309 0 0 3
##job 5 0 0 109 4 4
##job 6 0 0 4 375 38
##job 7 0 18 4 26 260
相反,如果您的有向图是从列到行:
work.list <- sort(unique(unlist(lapply(work.list, function(x) which(jobdat[,x] != 0)))))
已更新扩充问题:
随着新 jobdat
:
jobdat <- matrix(c(
1, 0, 1, 0, 0, 0, 0,
1, 1, 1, 0, 0, 0, 0,
1, 1, 1, 0, 0, 0, 0,
0, 0, 0, 1, 0, 0, 0,
0, 0, 0, 0, 1, 0, 0,
0, 0, 0, 0, 0, 1, 0,
0, 0, 0, 0, 0, 0, 1
),
nrow = 7, ncol = 7, byrow = TRUE,
dimnames = list(c("job 1","job 2","job 3","job 4","job 5","job 6","job 7"),
c("job 1","job 2","job 3","job 4","job 5","job 6","job 7")))
和work.list
中的相关职位列表:
work.list <- c(1,5,7)
计算扩充工作列表 aug.work.list
作为直接转到 work.list
中相关工作的工作集合。这将包括工作 2 和 3。请注意,我们在这里使用 which(jobdat[,x] != 0)
而不是 which(jobdat[x,] != 0)
来标识连接到 [= 中的相关工作 x
的工作(相关或不相关) 20=].
aug.work.list <- sort(unique(unlist(lapply(work.list, function(x) which(jobdat[,x] != 0)))))
##[1] 1 2 3 5 7
这导致:
jobdat.result <- jobdat[aug.work.list, aug.work.list]
## job 1 job 2 job 3 job 5 job 7
##job 1 1 0 1 0 0
##job 2 1 1 1 0 0
##job 3 1 1 1 0 0
##job 5 0 0 0 1 0
##job 7 0 0 0 0 1
现在,要去除不相关作业之间的联系,首先在 jobdat.result
中找到这些不相关作业的索引,这些索引是 aug.work.list
中不在 work.list
中的元素的索引
irrelevant.job.indices <- which(!(aug.work.list %in% work.list))
##[1] 2 3
请注意,这些不是不相关职位的职位编号,而是 jobdat.result
中对应于不相关职位编号的(行和列)索引。
在这种情况下,它们恰好对应于工作编号本身。
删除连接需要将 irrelevant.job.indices
索引的 jobdat.result
的子矩阵的非对角线设置为 0
。为此:
## first, keep diagonal values for irrelevant.job.indices
dvals <- diag(jobdat.result)[irrelevant.job.indices]
## set sub-matrix to zero (this will also set diagnal elements to zero)
jobdat.result[irrelevant.job.indices,irrelevant.job.indices] <- 0
## replace diagonal elements
diag(jobdat.result)[irrelevant.job.indices] <- dvals
结果是:
jobdat.result
## job 1 job 2 job 3 job 5 job 7
##job 1 1 0 1 0 0
##job 2 1 1 0 0 0
##job 3 1 0 1 0 0
##job 5 0 0 0 1 0
##job 7 0 0 0 0 1