社会网络分析(Social Network Analysis,SNA)逐步成为数据挖掘领域的又一新宠。SNA的本质是利用各样本间的关系(故也成为关系网络)来分析整体样本的群落现象,并分析出样本点在群落形成的作用以及群落间的关系。利用R语言中的igraph包实现SNA。
用R语言建立关系网络
(1) 原始数据准备
from<-c("a","a","e","b","b","c","d","d","d","f")
to<-c("c","e","c","e","c","d","g","g","f","d")
data<-data.frame(from=from,to=to)
data
## from to
## 1 a c
## 2 a e
## 3 e c
## 4 b e
## 5 b c
## 6 c d
## 7 d g
## 8 d g
## 9 d f
## 10 f d
# 然后读取每个样本点的名称:
(labels<-union(unique(data[,1]),unique(data[,2])))
## [1] "a" "e" "b" "c" "d" "f" "g"
# 建立点标识号向量id,并把其代表的样本名称labels作为元素名称.
ids<-1:length(labels)
names(ids)<-labels;ids
## a e b c d f g
## 1 2 3 4 5 6 7
# 通过向量ids中元素值和元素名称的映射关系,把数据框data转化为矩阵edges。
from<-as.character(data[,1]);to<-as.character(data[,2])
edges<-matrix(c(ids[from],ids[to]),ncol=2)
edges
## [,1] [,2]
## [1,] 1 4
## [2,] 1 2
## [3,] 2 4
## [4,] 3 2
## [5,] 3 4
## [6,] 4 5
## [7,] 5 7
## [8,] 5 7
## [9,] 5 6
## [10,] 6 5
(2) 建立关系网络
# 1) 使用graph.empty函数建立一个空的关系网络g(没有定义任何点和线的信息),当参数directed=TRUE时,该关系网络为有有向图,当directed=FALSE时为无向图
library(igraph)
g<-graph.empty(directed=F)
# 2)使用add.vertices函数向关系网络g中添加length(lables)个点vertices,并为各个点添加名称信息V(g)$label。
g<-add.vertices(g,length(labels))
V(g)$label=labels
# 3)使用add.edges函数向关系网络中添加线edges信息。
g<-add.edges(g,t(edges))
# 4)把重复的线合并,并把重复次数作为线权重weight。
E(g)$weight<-count.multiple(g);E(g)$weight
## [1] 1 1 1 1 1 1 2 2 2 2
g<-simplify(g,remove.multiple=TRUE,remove.loops=TRUE,edge.attr.comb="mean")
E(g)$weight
## [1] 1 1 1 1 1 1 2 2
# 这里的count.multiple(g)用于计算网络g中每条线的重复数。使用simplify函数把图中重复的线删除(remove.multiple=TRUE),并使用重复的次数来更新线权重E(g)$weight(edge.attr.comb="mean")
自此,就建立了一个完整的关系网络g。下面提取上述代码中的部门对象作为参数,并给出一段自定义的函数init.igraph用户建立关系网络
init.graph<-function(data,dir=F,rem.multi=T){
labels<-union(unique(data[,1]),unique(data[,2]))
ids<-1:length(labels);names(ids)<-labels
from<-as.character(data[,1]);to<-as.character(data[,2])
edges<-matrix(c(ids[from],ids[to]),ncol=2)
g<-graph.empty(directed=dir)
g<-add.vertices(g,length(labels))
V(g)$label<-labels
g<-add.edges(g,t(edges))
if(rem.multi){
E(g)$weight<-count.multiple(g)
g<-simplify(g,remove.multiple=TRUE,remove.loops=TRUE,edge.attr.comb="mean")
}
g
}
这里的参数data是包括点名称以及线数据的数据框。并且分为from列和to列。例如:
from<-c("a","a","e","b","b","c","d","d","d","f")
to<-c("c","e","c","e","c","d","g","g","f","d")
data<-data.frame(from=from,to=to)
参数dir是逻辑变量,设为TRUE时,表示建立有向图,否则是无向图。参数rem.multi是逻辑变量,设为TRUE时,表示删除重复变量并更新线权重weight,否则不删除并且线权重weight恒为1。
(3) 基础概念的R语言实现
依次使用init.graph函数建立无向图和有向图,并使用plot函数绘制图像。代码如下:
par(mfcol=c(1,2))
g.undir<-init.graph(data)
plot(g.undir,edge.width=E(g.undir)$weight,main="无向图 g.undir",
edge.label=E(g.undir)$weight)
g.undir<-init.graph(data,dir=T)
plot(g.undir,edge.width=E(g.undir)$weight,main="有向图 g.undir",
edge.label=E(g.undir)$weight)
par(mfcol=c(1,1))
这里通过设置plot函数的edge.width参数为E(g)$weight,使得权重较高的线更粗.