3 min read

igraph matrices

关联矩阵(incidence matrix)

我们生成的这个矩阵的原型是一个引证关系矩阵。 矩阵中的三行代表3篇文献,四列代表4篇引文。 1/2/3/4是在A/B/C前面发表的文献,A/B/C是后来发表的文献。 其中文献A引用了3/4,文献B引用了1/2/4,文献C引用了1/2/4。

library(igraph)
library(Matrix)

set.seed(3)
m <- matrix(data = sample(0:1, 12, replace = TRUE),nrow = 3)
rownames(m) <- LETTERS[1:3]
colnames(m) <- 1:4
m
##   1 2 3 4
## A 0 0 1 1
## B 1 1 0 1
## C 1 1 0 1

这样的一个引证关系,可以用下面的图表示。

bibliometrix::cocMatrix() 中将这种矩阵称为共现矩阵,Co-occurrence Matrix。

par(mar=c(1,1,1,1))

g1 <- graph_from_incidence_matrix(m,directed = TRUE,mode = "out") 
plot(g1)

上面的矩阵通过矩阵叉乘可以得到不同的邻接矩阵,用于生成新的网络。

矩阵和向量的计算

矩阵的点乘就是矩阵各个对应元素相乘, 这个时候要求两个矩阵必须同样大小。

https://blog.csdn.net/u013066730/article/details/57462299

矩阵的叉乘(乘法)就是矩阵A的第一行乘以矩阵B的第一列,各个元素对应相乘然后求和作为第一元素的值。 矩阵只有当左边矩阵的列数等于右边矩阵的行数时才可以相乘, 乘积矩阵的行数等于左边矩阵的行数,乘积矩阵的列数等于右边矩阵的列数。

向量的点乘和叉乘是矩阵算法的基础。

https://blog.csdn.net/dcrmg/article/details/52416832

向量的点乘,也叫向量的内积、数量积,对两个向量执行点乘运算, 就是对这两个向量对应位一一相乘之后求和的操作,点乘的结果是一个标量。

点乘的几何意义是可以用来表征或计算两个向量之间的夹角,以及在b向量在a向量方向上的投影。

两个向量的叉乘,又叫向量积、外积、叉积,叉乘的运算结果是一个向量而不是一个标量。并且两个向量的叉积与这两个向量组成的坐标平面垂直。

在 R 语言中,使用 %*% 计算矩阵的叉乘,而 crossprod()tcrossprod() 函数对算法进行了优化。

此外,crossprod() 对计算过程也进行了变动,同一个矩阵的叉乘时不需要预先转置。

下面的三个个计算结果一样。

m %*% t(m)
##   A B C
## A 2 1 1
## B 1 3 3
## C 1 3 3
crossprod(t(m),t(m))
##   A B C
## A 2 1 1
## B 1 3 3
## C 1 3 3
tcrossprod(m,m)
##   A B C
## A 2 1 1
## B 1 3 3
## C 1 3 3

下面的两个结果也一样。

t(m) %*% m
##   1 2 3 4
## 1 2 2 0 2
## 2 2 2 0 2
## 3 0 0 1 1
## 4 2 2 1 3
crossprod(m,m)
##   1 2 3 4
## 1 2 2 0 2
## 2 2 2 0 2
## 3 0 0 1 1
## 4 2 2 1 3

邻接矩阵(adjacency matrix)

m2 <- crossprod(m,m)
m2
##   1 2 3 4
## 1 2 2 0 2
## 2 2 2 0 2
## 3 0 0 1 1
## 4 2 2 1 3

共被引(co-citation)是指当两篇(或多篇)文献同时被后来一篇(或多篇)论文所引用的关系, 同时引用这两篇论文的文献数目则称为共被引强度。 文献的共被引关系会随着时间的变化而变化。 通过对文献共被引网络的研究可以探究科学的发展和演进动态。

根据共被引的定义,文献1和2同时被B和C引用,二者具有共被引关系,共被引强度是2。 同理,文献3和4之间的共被引强度是1, 文献1和3的共被引强度是0,文献2和3的共被引强度是0; 文献2和4的共被引强度是2,文献1和4的共被引强度是2。

g2 <- graph_from_adjacency_matrix(m2, mode = "undirected")
par(mar=c(1,1,1,1))
plot(g2,layout=layout_with_kk)

若文献A和文献B引用了相同的参考文献,则它们之间构成耦合关系(coupling)。 它们所包含相同参考文献的个数成为耦合强度。 如果两篇文献同时引用了1篇文献,则耦合度为1;若同时引用了3篇文献,则耦合度为3。 两篇文献拥有的共同参考文献越多,则其研究内容越相似。

耦合关系的邻接矩阵可以用转置后关联矩阵的叉乘来表示。

m3 <- crossprod(t(m),t(m))
m3
##   A B C
## A 2 1 1
## B 1 3 3
## C 1 3 3

文献B和C共同引用了1/2/4号文献,因此它们之间的耦合关系最强,数值为3。

g3 <- graph_from_adjacency_matrix(m3, mode = "undirected")
par(mar=c(1,1,1,1))
plot(g3)

从文献耦合的概念上看,一个文献引用的参考文献越多, 那么它将有越多的机会与其它文献建立耦合关系。 为了消除这种影响,通常需要对原始数据使用 Jaccard 或 Salton 方法进行标准化处理, 来计算相对的耦合强度。

bibliometrix::normalizeSimilarity() 提供了3种方法来标准化耦合矩阵。

method <- c("association", "jaccard", "inclusion","salton", "equivalence")
m3_list <- lapply(method, function(x){
  bibliometrix::normalizeSimilarity(m3,type = x)
})
## This version of bslib is designed to work with shiny version 1.5.0.9007 or higher.
names(m3_list) <- method
m3_list
## $association
## 3 x 3 sparse Matrix of class "dsCMatrix"
##           A         B         C
## A 0.5000000 0.1666667 0.1666667
## B 0.1666667 0.3333333 0.3333333
## C 0.1666667 0.3333333 0.3333333
## 
## $jaccard
## 3 x 3 sparse Matrix of class "dsCMatrix"
##      A    B    C
## A 1.00 0.25 0.25
## B 0.25 1.00 1.00
## C 0.25 1.00 1.00
## 
## $inclusion
## 3 x 3 sparse Matrix of class "dsCMatrix"
##     A   B   C
## A 1.0 0.5 0.5
## B 0.5 1.0 1.0
## C 0.5 1.0 1.0
## 
## $salton
## 3 x 3 sparse Matrix of class "dsCMatrix"
##           A         B         C
## A 1.0000000 0.4082483 0.4082483
## B 0.4082483 1.0000000 1.0000000
## C 0.4082483 1.0000000 1.0000000
## 
## $equivalence
## 3 x 3 sparse Matrix of class "dsCMatrix"
##           A         B         C
## A 1.0000000 0.1666667 0.1666667
## B 0.1666667 1.0000000 1.0000000
## C 0.1666667 1.0000000 1.0000000

标准化的邻接矩阵最大值都不超过1,因此在创建网络的时候要使用“weighted = TRUE”模式。 这样,矩阵的强度将会转变为边的属性。

par(mfrow=c(2,3))
success <- lapply(seq_along(m3_list), function(x){
  par(mar=c(1,1,1,1))
  graph_from_adjacency_matrix(m3_list[[x]], mode = "undirected", weighted = TRUE) %>% 
    plot(main=method[[x]])
})

乍看上去,生成的网络是一样的,但事实上边的属性不一样。 如果我们把边的宽度映射到“weight”属性,则仍然可以发现文献B和C之间的耦合关系是最强的。

par(mfrow=c(2,3))
success <- lapply(seq_along(m3_list), function(x){
  par(mar=c(1,1,1,1))
  g3_weighted <- graph_from_adjacency_matrix(m3_list[[x]], mode = "undirected", weighted = TRUE)
  E(g3_weighted)$width  <- edge.attributes(g3_weighted)$weight*5
  plot(g3_weighted, main=method[[x]])
})

对于耦合网络来说,图中的 loop 是没有意义的。可以使用 igraph::simplify() 来去掉。

g4 <- simplify(g3, remove.multiple = FALSE, remove.loops = TRUE)
plot(g4)