在R中使用igraph进行Louvain社区检测 - 边缘和顶点的格式

3
我有一个得分的相关矩阵,想要在R中使用igraph的Louvain算法进行社区检测。我用cor2dist将相关矩阵转换为距离矩阵,如下所示: distancematrix <- cor2dist(correlationmatrix) 这样就得到了一个400 x 400的距离矩阵,距离范围在0到2之间。然后我使用http://kateto.net/networks-r-igraph(3.1节)中的以下方法,制作了边缘列表(距离)和顶点(400个个体)的列表。
library(igraph)
test <- as.matrix(distancematrix)
mode(test) <- "numeric"
test2 <- graph.adjacency(test, mode = "undirected", weighted = TRUE, diag = TRUE)
E(test2)$weight
get.edgelist(test2)

接着,我将“起始点”和“终止点”边缘列表及对应的权重写成了csv文件:

edgeweights <-E(test2)$weight
write.csv(edgeweights, file = "edgeweights.csv")
fromtolist <- get.edgelist(test2)
write.csv(fromtolist, file = "fromtolist.csv")

从这两个文件中,我生成了一个名为“nodes.csv”的.csv文件,其中只包含400个个体的所有顶点ID:

id
1
2
3
4
...
400

还有一个名为"edges.csv"的csv文件,它详细描述了每个节点之间的“from”和“to”,并提供了每条边的权重(即距离度量):

from    to   weight
1       2    0.99
1       3    1.20
1       4    1.48
...
399     400  0.70

我随后尝试使用节点和边列表创建igraph对象,并以以下方式运行louvain聚类:

nodes <- read.csv("nodes.csv", header = TRUE, as.is = TRUE)
edges <- read.csv("edges.csv", header = TRUE, as.is = TRUE)
clustergraph <- graph_from_data_frame(edges, directed = FALSE, vertices = nodes)
clusterlouvain <- cluster_louvain(clustergraph)

不幸的是,这无法正确执行louvain社区检测。我预期这会返回大约2-4个不同的社区,类似于这里可以绘制出来,但是sizes(clusterlouvain)返回:

Community sizes
 1 
 400

这段文字表明所有个体都被归入同一个社区。聚类也立即运行(即几乎没有计算时间),这也让我认为它没有正确工作。

我的问题是:有谁能提供建议,解释为什么cluster_louvain方法没有起作用,只识别出一个社区?我认为可能是我错误地指定了距离矩阵或边/节点,或以其他方式未正确提供正确的输入给cluster_louvain方法。我对R还比较陌生,因此非常感谢任何建议。我已成功地在相同的距离矩阵上使用了其他社区检测方法(即k-means),其识别出2-3个社区,但我想了解这里做错了什么。

我知道有多个关于在R中使用igraph的查询,但我没有找到一个明确指定边和节点格式(从相关性矩阵)的查询,以正确地进行louvain社区检测。

感谢您的任何建议!如果需要,我可以提供更多信息。

1个回答

8

我相信 cluster_louvain 对您的数据进行了正确的操作。 问题出在您的图上。您的代码中包含了一行 get.edgelist(test2),这会产生大量输出。请尝试使用以下代码替换:

vcount(test2)
ecount(test2)

既然你说你的相关矩阵是400x400,我预计vcount将会是400,ecount将会是79800=400*399/2。按照你的构建方式,每个节点都直接连接到所有其他节点。当然,只有一个大社区。
我怀疑你试图做的是将相关的变量分组。如果相关系数接近零,则这些变量应该是不相关的。似乎不太清楚的是,对于相关系数接近-1的变量要怎么办。你想让它们相互连接还是不连接?我们可以两种方式都实现。
你没有提供任何数据,因此我将使用mlbench包中的Ionosphere数据进行说明。我会尽可能地模仿你的代码,但会更改一些变量名。同时,为了我的目的,将边写入文件然后再读回来是毫无意义的,所以我将直接使用构建出的边。
首先,假设你希望相关系数接近-1的变量彼此相连。
library(igraph)
library(mlbench)    # for Ionosphere data
library(psych)      # for cor2dist
data(Ionosphere)

correlationmatrix = cor(Ionosphere[, which(sapply(Ionosphere, class) == 'numeric')])
distancematrix <- cor2dist(correlationmatrix)

DM1 <- as.matrix(distancematrix)
## Zero out connections where there is low (absolute) correlation
## Keeps connection for cor ~ -1
## You may wish to choose a different threshhold
DM1[abs(correlationmatrix) < 0.33] = 0

G1 <- graph.adjacency(DM1, mode = "undirected", weighted = TRUE, diag = TRUE)
vcount(G1)
[1] 32
ecount(G1)
[1] 140

这不是一个完全连接的图!现在让我们找到社区。

clusterlouvain <- cluster_louvain(G1)
plot(G1, vertex.color=rainbow(3, alpha=0.6)[clusterlouvain$membership])

社区1

如果您不想将负相关的变量连接起来,只需去掉上面的绝对值即可。这样应该会少得多。

DM2 <- as.matrix(distancematrix)
## Zero out connections where there is low correlation
DM2[correlationmatrix < 0.33] = 0

G2 <- graph.adjacency(DM2, mode = "undirected", weighted = TRUE, diag = TRUE)
clusterlouvain <- cluster_louvain(G2)
plot(G2, vertex.color=rainbow(4, alpha=0.6)[clusterlouvain$membership])

Community 2


非常感谢您的帮助!问题已经解决了。我不确定 cluster_louvain 是否会自动阈值化边缘列表以仅使用更高加权边缘(即更高的相关性)来推导社区。但是在思考后,我意识到 cluster_louvain 当然会使用所有边缘进行社区检测,因为它不会自动知道边缘表示相关性(或任何其他度量),其中只有更高的值是有意义的;这是我们作为研究人员在相关性/输入矩阵中指定的。再次感谢您有用的解释和解决方案。 - A.Robin
我已经在这里提出了一个后续问题,关于我运行此分析时的情况[https://stackoverflow.com/questions/49856205/louvain-community-detection-in-r-using-igraph-assigns-alternating-group-member] - 它不是直接相关的,但对于任何试图正确导入相关矩阵到R中进行'cluster_louvain'的人来说,这可能是一个有用的参考。再次非常感谢您的帮助! - A.Robin

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