基于Spark GraphX的图形数据分析

一、图(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、有向图、无向图

  1. 有向图
G=(V,E)
V={
    
    A,B,C,D,E}
E={
    
    <A,B>,<B,C>,<B,D>,<C,E>,<D,A>,<E,D>}

如下图所示:

有向图

  1. 无向图
G=(V,E)
V={
    
    A,B,C,D,E}
E={
    
    (A,B),(A,D),(B,C),(B,D),(C,E),(D,E)}

如下图所示:

无向图

3、有环图、无环图

  1. 有环图
    包含一系列顶点连接的回路(环路)

有环图

  1. 无环图
    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

猜你喜欢

转载自blog.csdn.net/qq_42578036/article/details/110184660