一、图(Graph)的基本概念
1、图是由顶点集合(vertex)及顶点间的关系集合(边edge)组成的一种网状数据结构
- 通常表示为二元组:Gragh=(V,E)
- 可以对事物之间的关系建模
2、应用场景
- 在地图应用中寻找最短路径
- 社交网络关系
- 网页间超链接关系
二、图的术语
1、顶点(Vertex)、边(Edge)
Graph=(V,E)
集合V={
v1,v2,v3}
集合E={
(v1,v2),(v1,v3),(v2,v3)}
如下图所示:
2、有向图、无向图
- 有向图
G=(V,E)
V={
A,B,C,D,E}
E={
<A,B>,<B,C>,<B,D>,<C,E>,<D,A>,<E,D>}
如下图所示:
- 无向图
G=(V,E)
V={
A,B,C,D,E}
E={
(A,B),(A,D),(B,C),(B,D),(C,E),(D,E)}
如下图所示:
3、有环图、无环图
- 有环图
包含一系列顶点连接的回路(环路)
- 无环图
DAG即为有向无环图
4、度
度:一个顶点所有边的数量
- 出度:指从当前顶点指向其他顶点的边的数量
- 入度:其他顶点指向当前顶点的边的数量
如上图中:
顶点2的度为1,出度:0,入度:1
顶点8的度为3,出度:1,入度:2
顶点10的度为2,出度:0,入度:2
顶点11的度为5,出度:3,入度:2
…
5、图的经典表示法 – 邻接矩阵
- 对于每条边,矩阵中相应单元格值为1
- 对于每个循环,矩阵中相应单元格值为2,方便在行或列上求得顶点度数
三、Spark GraphX
1、Spark GraphX 简介
GraphX是Spark提供分布式图计算API
GraphX特点:
- 基于内存实现了数据的复用与快速读取
- 通过弹性分布式属性图(Property Graph)统一了图视图与表视图
- 与Spark Streaming、Spark SQL和Spark MLlib等无缝衔接
2、GraphX 核心抽象
弹性分布式属性图(Resilient Distributed Property Graph)
- 顶点和边都带属性的有向多重图
- 一份物理存储,两种视图
- 对Graph视图的所有操作,最终都会转换成其关联的Table视图的RDD操作来完成
3、GraphX API
- Graph[VD,ED]
- VertexRDD[VD]
- EdgeRDD[ED]
- EdgeTriplet[VD,ED]
- Edge:样例类
- VertexId:Long的别名
四、创建并使用 Graph
1、导入Spark Graph包
import org.apache.spark.graphx._
2、创建 vertices 顶点 RDD
val vertices = sc.makeRDD(Seq((1L,1),(2L,2),(3L,3)))
3、创建 edges 边 RDD
val edges = sc.makeRDD(Seq(Edge(1L,2L,1),Edge(2L,3L,2)))
4、创建 Graph 对象
val graph = Graph(vertices,edges)
5、通过文件加载 Graph 对象
followers.txt
2 3
3 4
1 4
2 4
加载语句:
val graph = GraphLoader.edgeListFile(sc, "file:///opt/followers.txt")
6、获取 Graph 图对象的 vertices(顶点)信息
graph.vertices.collect.foreach(println)
7、获取 Graph 图对象的 edges(边)信息
graph.edges.collect.foreach(println)
8、获取 Graph 图对象的 triplets(所有)信息
graph.triplets.collect.foreach(println)
五、构建用户合作关系属性图
1、创建顶点 RDD
val users= sc.parallelize(Array((3L,("rxin","student")),
(7L,("jgonzal","postdoc")),
(5L,("franklin","professor")),
(2L,("istoica","professor"))))
2、创建边 RDD
val relationship=sc.parallelize(Array(
Edge(3L,7L,"Colla"),
Edge(5L,3L,"Advisor"),
Edge(2L,5L,"Colleague"),
Edge(5L,7L,"Pi")))
3、创建 Graph 对象
val graphUser=Graph(users,relationship)
1)顶点属性
- 用户名
- 职业
2)边属性
- 合作关系
4、Graph 图的顶点、边的获取
graphUser.vertices.collect.foreach(println)
graphUser.edges.collect.foreach(println)
graphUser.triplets.collect.foreach(println)
六、构建用户社交网络关系
- 顶点:用户名、年龄
- 边:打call次数
1、创建 Graph 对象
//创建顶点RDD
val userRdd=sc.parallelize(Array(
(1L,("Alice",28)),
(2L,("Bob",27)),
(3L,("Charlie",65)),
(4L,("David",42)),
(5L,("Ed",55)),
(6L,("Fran",50))
))
//创建边RDD
val usercallRdd=sc.makeRDD(Array(
Edge(2L,1L,7),
Edge(3L,2L,4),
Edge(4L,1L,1),
Edge(2L,4L,2),
Edge(5L,2L,5),
Edge(5L,3L,8),
Edge(3L,6L,3),
Edge(5L,6L,3)
))
//创建图
val userCallGraph=Graph(userRdd,usercallRdd)
2、数据分析
找出大于30岁的用户
userCallGraph.vertices.filter(v=>v._2._2.toInt>30).collect.foreach(println)
分析结果:
(4,(David,42))
(5,(Ed,55))
(6,(Fran,50))
(3,(Charlie,65))
找出打call超过5次的
userCallGraph.triplets.filter(x=>x.attr>5).collect.foreach(x=>println(x.srcAttr._1+" like "+ x.dstAttr._1+" stage:"+x.attr))
分析结果:
Bob like Alice stage:7
Ed like Charlie stage:8