sta*_*555 5 r graph cluster-analysis edges nodes
我有如下所示的数据:https : //imgur.com/a/1hOsFpF
第一个数据集是标准格式数据集,其中包含人员及其财务属性的列表。
第二个数据集包含这些人之间的“关系”——他们互相支付了多少,以及他们彼此欠了多少。
我有兴趣了解更多关于网络和基于图的聚类 - 但我试图更好地了解什么类型的情况需要基于网络的聚类,即我不想在不需要的地方使用图聚类(避免“方钉圆孔"类型情况)。
使用 R,首先我创建了一些假数据:
library(corrr)
library(dplyr)
library(igraph)
library(visNetwork)
library(stats)
# create first data set
Personal_Information <- data.frame(
"name" = c("John", "Jack", "Jason", "Jim", "Julian", "Jack", "Jake", "Joseph"),
"age" = c("41","33","24","66","21","66","29", "50"),
"salary" = c("50000","20000","18000","66000","77000","0","55000","40000"),
"debt" = c("10000","5000","4000","0","20000","5000","0","1000"
)
Personal_Information$age = as.numeric(Personal_Information$age)
Personal_Information$salary = as.numeric(Personal_Information$salary)
Personal_Information$debt = as.numeric(Personal_Information$debt)
create second data set
Relationship_Information <-data.frame(
"name_a" = c("John","John","John","Jack","Jack","Jack","Jason","Jason","Jim","Jim","Jim","Julian","Jake","Joseph","Joseph"),
"name_b" = c("Jack", "Jason", "Joseph", "John", "Julian","Jim","Jim", "Joseph", "Jack", "Julian", "John", "Joseph", "John", "Jim", "John"),
"how_much_they_owe_each_other" = c("10000","20000","60000","10000","40000","8000","0","50000","6000","2000","10000","10000","50000","12000","0"),
"how_much_they_paid_each_other" = c("5000","40000","120000","20000","20000","8000","0","20000","12000","0","0","0","50000","0","0")
)
Relationship_Information$how_much_they_owe_each_other = as.numeric(Relationship_Information$how_much_they_owe_each_other)
Relationship_Information$how_much_they_paid_each_other = as.numeric(Relationship_Information$how_much_they_paid_each_other)
Run Code Online (Sandbox Code Playgroud)
然后,我运行了一个标准的 K-Means 聚类算法(在第一个数据集上)并绘制了结果:
# Method 1 : simple k means analysis with 2 clusters on Personal Information dataset
cl <- kmeans(Personal_Information[,c(2:4)], 2)
plot(Personal_Information, col = cl$cluster)
points(cl$centers, col = 1:2, pch = 8, cex = 2)
Run Code Online (Sandbox Code Playgroud)
这就是我通常会如何处理这个问题。现在,我想看看我是否可以对此类问题使用图聚类。
首先,我创建了一个加权相关网络(http://www.sthda.com/english/articles/33-social-network-analysis/136-network-analysis-and-manipulation-using-r/)
首先,我创建了加权相关网络(使用第一个数据集):
res.cor <- Personal_Information[, c(2:4)] %>%
t() %>% correlate() %>%
shave(upper = TRUE) %>%
stretch(na.rm = TRUE) %>%
filter(r >= 0.8)
graph <- graph.data.frame(res.cor, directed=F)
graph <- simplify(graph)
plot(graph)
Run Code Online (Sandbox Code Playgroud)
然后,我运行了图聚类算法:
#run graph clustering (also called communiy dectection) on the correlation network
fc <- fastgreedy.community(graph)
V(graph)$community <- fc$membership
nodes <- data.frame(id = V(graph)$name, title = V(graph)$name, group = V(graph)$community)
nodes <- nodes[order(nodes$id, decreasing = F),]
edges <- get.data.frame(graph, what="edges")[1:2]
visNetwork(nodes, edges) %>%
visOptions(highlightNearest = TRUE, nodesIdSelection = TRUE)
Run Code Online (Sandbox Code Playgroud)
这似乎有效 - 但我不确定这是否是解决这个问题的最佳方式。
有人可以提供一些建议吗?我把这个问题复杂化了吗?
谢谢
(首先是一些背景知识,以便从您所描述的内容中了解问题的本质)您有 2 个数据集,因此会产生 2 个数据结构:Personal_Information和Relationship_Information。您有一组看似唯一的实体,因为 中没有名称重复 Personal_Information,因此,如果您知道这些实体之间具有连接信息,我们可以将它们称为网络中的节点,其中它们的互连性可以产生一个网络,其中社区检测算法可以发现/分配/检测一些社区。所以,
在您在代码中提供的此信息的示例用法中,您似乎仅使用graph仅从Personal_Information res.cor <- Personal_Information[, c(2:4)] %>% ...而不是构建的数据Relationship_Information。这意味着您正在每个人的变量之间建立关系,这些变量是他们作为网络中的节点所固有的,而不是他们因相互关联的交互而产生的数据。要了解你在这里做什么,你的方向就像在说;我将在人们的性格特征之间建立一个网络,并忽略他们之间的关联,即使我有数据。我将研究这些个性特征之间如何相互关联,然后查看哪些特征值组具有彼此跟随的值(分组相关)
因此,找到多个人的节点(人)特征之间的相关性就可以了,然后生成该信息的矩阵也可以,然后从中生成图/网络也可以。您生成的图表的结果(您称为graph),viafc <- fastgreedy.community(graph)是您获得的结果是;每个人的哪些变量组是相互相关的。例如,var1 和 var2 之间有很强的相关性,但是 var2 和 var3 之间有很强的负相关性,因此 var2 和 var3 之间的边缘将推动它们处于不同的社区,也推动 var1 处于不同的社区中。来自 var3 的社区,因为它与 var2 (亲密的朋友)紧密相连。这些信息有什么用处?它可以帮助您了解变量如何作为组存在,这样如果您有一个新人的 var2 值较低,并且您不知道 var1 或 var3 的值;您可能会期望 var1 也会很低,而 var3 也会很高。如果您获取人员数据的协方差,则可以获取特征向量并有效地执行 PCA,这将为您提供包含这种性质信息的向量。
但是,这不会产生有关您在Relationship_Information数据中观察/测量的网络边缘的信息,这些信息描述了社区数据信息而不是节点数据。该数据集看起来像一个邻接列表,它是一种数据结构,列出前 2 列作为 col1 中的节点源、col2 中的节点目标以及 col3 中的边权重,并且如果 col2 和 col1 中的节点名称相同(交换)具有相同边权重的网络具有对称边(无向),否则它是有向的。由于您的数据有 2 个边列(col3 和 col4),您可以使用 col1、col2、col3 生成一个网络,使用 col1、col2、col4 生成另一个网络,或者...您可以使用以下命令生成一个网络
这取决于您如何使用这些值定义边缘。您想要从adj1或adj2生成一个网络,然后从该网络应用社区检测。可以将其视为该数据集中的那些付款,就像社交媒体上的互动一样,就像点赞和提及将人们联系在一起一样。此处的社区结果显示根据您使用的边在经济上紧密相连的社区的标签,您可以应用类似的算法Louvain algorithm来执行此操作。
但这并没有同时使用节点数据和边缘数据(人员数据和交换数据)。他们正在回答不同的问题。
将 K-Means 应用于节点特征数据正在回答与社区检测算法不同的问题。
因此,这些问题在使用聚类和社区检测时是独立的,因为它们使用独立收集的数据集。电子表格彼此不依赖,数据也不依赖。这并不意味着它们的数据没有交叉信息。您可以让这些特征影响边缘。因此,在呈现它时,您需要进行两项单独的调查。
(上面的另一个答案提到了基于融合的方法来分析节点数据和边缘数据一起的数据,但这似乎不是您的问题。您是否尝试一起使用两个数据集?如果是这样,最简单的方法是使用具有良好实现的方法和像 SGC(简单的图卷积神经网络)这样的“图神经网络”是一个很好的建议,尽管这听起来很吓人,但您可以向它提供由您创建的支付网络组成的邻接矩阵然后是节点属性/特征。Python 的 DGL 库非常适合此操作。如果需要,您可以使用缩放数据进行无监督操作。)