从邻接矩阵快速计算任意一对节点之间共享邻居的数量
Quickly calculate the number of shared neighbor between any pair of nodes from an adjacency matrix
我想知道是否有一种方法可以从邻接矩阵(如下图所示)快速计算任何节点对之间的共享邻居数(即连接到节点 i 和 j 的节点数) ) 然后 return 矩阵格式的输出?
我参考了以下帖子,
但似乎无法找到很多线索来实现我想要实现的目标。有人告诉我这可以直接计算为 adjm'
*adjm
,但我不确定这是否有意义。如果有人能对此有所了解,我们将不胜感激。
# create an adj. matrix
adjm <- matrix(sample(0:1, 100, replace=TRUE, prob=c(0.6,0.4)), nc=10)
# set diagonal element to 0
diag(adjm) <- 0
# making it symmetric
adjm[lower.tri(adjm)] = t(adjm)[lower.tri(adjm)]
是的,你可以通过计算矩阵得到共享邻居的数量
adjm' 和 adjm 的乘积。由于您使用的是 R,因此 adjm'*adjm
表示
矩阵的分量乘积。我们想要矩阵乘积,
所以你需要使用 %*%。我将在下面使用它。
为了简化符号,我将表示 adjm = A 其中
如果节点 i 和 j 之间存在 link(它们是邻居),则 A[i,j] 为 1
并且 A[i,j] = 0 否则。
让我们计算 t(A) %*% A。
t(A)%*%A的第i-j个坐标为
(t(A) %*% A)[i,j] =
sum(t(A)[i,k] * A[k,j]) =
sum(A[k,i] * A[k,j])
和中的所有乘积不是 0 就是 1。
如果A[k,i]=1且A[k,j]=1,则乘积为1,
否则为零。所以 (t(A)%*%A)[i,j]
等于
A[k,i]=1 和
A[k,j]=1。但是 A[k,i]=1 表示 k 是 i 的邻居
A[k,j]=1 表示 k 是 j 的邻居,所以
(t(A)%*%A)[i,j]
等于不同k的个数
其中 k 是 i 和 j 的邻居。
让我们在您的示例中尝试一下。为了让结果
可重现,我设置了 random.seed.
library(igraph)
## For reproducibility
set.seed(1492)
# create an adj. matrix
adjm <- matrix(sample(0:1, 100, replace=TRUE, prob=c(0.6,0.4)), nc=10)
# set diagonal element to 0
diag(adjm) <- 0
# making it symmetric
adjm[lower.tri(adjm)] = t(adjm)[lower.tri(adjm)]
Shared = t(adjm) %*% adjm
g = graph_from_adjacency_matrix(adjm, mode = "undirected")
plot(g)
例如,注意 Shared[1,4] = 4。
那是因为节点 1 和 4 有四个共享邻居,
节点 2、3、6 和 9。Shared[5,7]=0 因为节点 5 和 7
没有共同的邻居。
我觉得已经超级简洁了,强烈推荐!
下面是图论的解法,可能效率不高:
> nb <- neighborhood(g,mindist = 1)
> outer(nb, nb, FUN = Vectorize(function(a, b) length(intersect(a, b))))
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] 6 1 1 4 2 2 2 5 3 1
[2,] 1 3 2 0 1 3 0 1 2 1
[3,] 1 2 4 1 2 4 1 1 3 3
[4,] 4 0 1 4 2 1 1 3 2 1
[5,] 2 1 2 2 4 2 0 1 3 2
[6,] 2 3 4 1 2 5 1 2 3 3
[7,] 2 0 1 1 0 1 2 2 1 1
[8,] 5 1 1 3 1 2 2 5 3 1
[9,] 3 2 3 2 3 3 1 3 7 3
[10,] 1 1 3 1 2 3 1 1 3 4
> t(adjm) %*% adjm
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] 6 1 1 4 2 2 2 5 3 1
[2,] 1 3 2 0 1 3 0 1 2 1
[3,] 1 2 4 1 2 4 1 1 3 3
[4,] 4 0 1 4 2 1 1 3 2 1
[5,] 2 1 2 2 4 2 0 1 3 2
[6,] 2 3 4 1 2 5 1 2 3 3
[7,] 2 0 1 1 0 1 2 2 1 1
[8,] 5 1 1 3 1 2 2 5 3 1
[9,] 3 2 3 2 3 3 1 3 7 3
[10,] 1 1 3 1 2 3 1 1 3 4
如果图是无向的,那么共享邻居数的矩阵就是A.A
,这里我用.
表示矩阵乘积。正如其他人所说,R 中正确的运算符是 %*%
。 不需要转置,因为在无向情况下,邻接矩阵是对称的:A' = A
.
如果图是有向的,我们假设A_{ij}
表示从i
到j
的连接数(这是igraph的解读)。
然后A'.A
的i,j
元素给出同时指向i
和j
的节点数(i <- v -> j
),A.A'
给出了 i
和 j
指向的节点数 (i -> v <- j
)。这些数量有时分别称为 cocitation 和 书目耦合 ,并且可以计算 using cocitation()
and bibcoupling()
in igraph。在无向情况下,这两个函数 return 相同,因此您可以使用其中一个。
我想知道是否有一种方法可以从邻接矩阵(如下图所示)快速计算任何节点对之间的共享邻居数(即连接到节点 i 和 j 的节点数) ) 然后 return 矩阵格式的输出?
我参考了以下帖子,
但似乎无法找到很多线索来实现我想要实现的目标。有人告诉我这可以直接计算为 adjm'
*adjm
,但我不确定这是否有意义。如果有人能对此有所了解,我们将不胜感激。
# create an adj. matrix
adjm <- matrix(sample(0:1, 100, replace=TRUE, prob=c(0.6,0.4)), nc=10)
# set diagonal element to 0
diag(adjm) <- 0
# making it symmetric
adjm[lower.tri(adjm)] = t(adjm)[lower.tri(adjm)]
是的,你可以通过计算矩阵得到共享邻居的数量
adjm' 和 adjm 的乘积。由于您使用的是 R,因此 adjm'*adjm
表示
矩阵的分量乘积。我们想要矩阵乘积,
所以你需要使用 %*%。我将在下面使用它。
为了简化符号,我将表示 adjm = A 其中 如果节点 i 和 j 之间存在 link(它们是邻居),则 A[i,j] 为 1 并且 A[i,j] = 0 否则。
让我们计算 t(A) %*% A。
t(A)%*%A的第i-j个坐标为
(t(A) %*% A)[i,j] =
sum(t(A)[i,k] * A[k,j]) =
sum(A[k,i] * A[k,j])
和中的所有乘积不是 0 就是 1。
如果A[k,i]=1且A[k,j]=1,则乘积为1,
否则为零。所以 (t(A)%*%A)[i,j]
等于
A[k,i]=1 和
A[k,j]=1。但是 A[k,i]=1 表示 k 是 i 的邻居
A[k,j]=1 表示 k 是 j 的邻居,所以
(t(A)%*%A)[i,j]
等于不同k的个数
其中 k 是 i 和 j 的邻居。
让我们在您的示例中尝试一下。为了让结果 可重现,我设置了 random.seed.
library(igraph)
## For reproducibility
set.seed(1492)
# create an adj. matrix
adjm <- matrix(sample(0:1, 100, replace=TRUE, prob=c(0.6,0.4)), nc=10)
# set diagonal element to 0
diag(adjm) <- 0
# making it symmetric
adjm[lower.tri(adjm)] = t(adjm)[lower.tri(adjm)]
Shared = t(adjm) %*% adjm
g = graph_from_adjacency_matrix(adjm, mode = "undirected")
plot(g)
例如,注意 Shared[1,4] = 4。
那是因为节点 1 和 4 有四个共享邻居,
节点 2、3、6 和 9。Shared[5,7]=0 因为节点 5 和 7
没有共同的邻居。
我觉得
下面是图论的解法,可能效率不高:
> nb <- neighborhood(g,mindist = 1)
> outer(nb, nb, FUN = Vectorize(function(a, b) length(intersect(a, b))))
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] 6 1 1 4 2 2 2 5 3 1
[2,] 1 3 2 0 1 3 0 1 2 1
[3,] 1 2 4 1 2 4 1 1 3 3
[4,] 4 0 1 4 2 1 1 3 2 1
[5,] 2 1 2 2 4 2 0 1 3 2
[6,] 2 3 4 1 2 5 1 2 3 3
[7,] 2 0 1 1 0 1 2 2 1 1
[8,] 5 1 1 3 1 2 2 5 3 1
[9,] 3 2 3 2 3 3 1 3 7 3
[10,] 1 1 3 1 2 3 1 1 3 4
> t(adjm) %*% adjm
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] 6 1 1 4 2 2 2 5 3 1
[2,] 1 3 2 0 1 3 0 1 2 1
[3,] 1 2 4 1 2 4 1 1 3 3
[4,] 4 0 1 4 2 1 1 3 2 1
[5,] 2 1 2 2 4 2 0 1 3 2
[6,] 2 3 4 1 2 5 1 2 3 3
[7,] 2 0 1 1 0 1 2 2 1 1
[8,] 5 1 1 3 1 2 2 5 3 1
[9,] 3 2 3 2 3 3 1 3 7 3
[10,] 1 1 3 1 2 3 1 1 3 4
如果图是无向的,那么共享邻居数的矩阵就是A.A
,这里我用.
表示矩阵乘积。正如其他人所说,R 中正确的运算符是 %*%
。 不需要转置,因为在无向情况下,邻接矩阵是对称的:A' = A
.
如果图是有向的,我们假设A_{ij}
表示从i
到j
的连接数(这是igraph的解读)。
然后A'.A
的i,j
元素给出同时指向i
和j
的节点数(i <- v -> j
),A.A'
给出了 i
和 j
指向的节点数 (i -> v <- j
)。这些数量有时分别称为 cocitation 和 书目耦合 ,并且可以计算 using cocitation()
and bibcoupling()
in igraph。在无向情况下,这两个函数 return 相同,因此您可以使用其中一个。