基于Spark GraphX的图形数据分析

本文深入探讨了图计算的需求和图的概念,包括顶点、边、有向图、无向图和度等。重点介绍了Spark GraphX,它是一个分布式图计算API,具备高效的数据复用和快速读取特性。文中详细阐述了GraphX的核心抽象、API,如VertexRDD、EdgeRDD和属性算子,以及如何使用它们进行图的结构和属性变换。此外,还讲解了PageRank和Connected Component等图算法的应用,并给出了计算用户粉丝数量的练习案例。
摘要由CSDN通过智能技术生成

1、为什么需要图计算

  • 许多大数据以大规模图或网络的形式呈现
  • 许多非图结构的大数据,常会被转换为图模型进行分析
  • 图数据结构很好地表达了数据之间的关联性

2、图的概念

2.1 图的基本概念及应用场景

图是由顶点集合(vertex)及顶点间的关系集合(边edge)组成的一种网状数据结构

  • 通常表示为二元组:Gragh=(V,E)
  • 可以对事物之间的关系建模

应用场景

  • 在地图应用中寻找最短路径
  • 社交网络关系
  • 网页间超链接关系

2.2 图的术语

2.2.1 顶点(Vertex)和边(Edge)

一般关系图中,事物为顶点,关系为边
定义一个图:

Graph=(V,E)
集合V={
   v1,v2,v3}
集合E={
   (v1,v2),(v1,v3),(v2,v3)}

在这里插入图片描述

2.2.2 有向图和无向图

  • 有向图:在有向图中,一条边的两个顶点一般扮演者不同的角色,比如父子关系、页面A连接向页面B;
G=(V,E)
V={
   A,B,C,D,E}
E={
   <A,B>,<B,C>,<B,D>,<C,E>,<D,A>,<E,D>}  //关系用尖括号表示

在这里插入图片描述

  • 无向图:在一个无向图中,边没有方向,即关系都是对等的,比如qq中的好友。
G=(V,E)
V={
   A,B,C,D,E}
E={
   (A,B),(A,D),(B,C),(B,D),(C,E),(D,E)}

在这里插入图片描述

2.2.3 有环图和无环图

  • 有环图:包含一系列顶点连接的回路(环路),有环图是包含循环的,一系列顶点连接成一个环,在有环图中,如果不关心终止条件,算法可能永远在环上执行,无法退出。

在这里插入图片描述

  • 无环图:不包含循环,不能形成环,DAG即为有向无环图
    在这里插入图片描述

2.2.4 度

指一个顶点所有边的数量。

  • 出度:指从当前顶点指向其他顶点的边的数量
  • 入度:其他顶点指向当前顶点的边的数量
    在这里插入图片描述

2.3 图的经典表示法

邻接矩阵:
在这里插入图片描述
1、对于每条边,矩阵中相应单元格值为1
2、对于每个循环,矩阵中相应单元格值为2,方便在行或列上求得顶点度数

3、Spark GraphX

3.1 简介

  • GraphX是Spark提供分布式图计算API

  • GraphX特点:

    • 基于内存实现了数据的复用与快速读取
    • 通过弹性分布式属性图(Property Graph)统一了图视图与表视图
    • 与Spark Streaming、Spark SQL和Spark MLlib等无缝衔接
  • 针对某些领域,如社交网络、语言建模等,graph-parallel系统可以高效地执行复杂的图形算法,比一般的data-parallel系统更快

  • Graphx是将graph-parallel的data-parallel统一到一个系统中。允许用户将数据当成一个图或一个集合RDD,而简化数据移动或复杂操作。

3.2 GraphX核心抽象

  • 弹性分布式属性图(Resilient Distributed Property Graph)

    • 顶点和边都带属性的有向多重图

在这里插入图片描述
在这里插入图片描述

  • 一份物理存储,两种视图

在这里插入图片描述
对Graph视图的所有操作,最终都会转换成其关联的Table视图的RDD操作来完成。

3.3 GraphX API

  • Graph[VD,ED]
  • VertexRDD[VD]
  • EdgeRDD[ED]
  • EdgeTriplet[VD,ED]
  • Edge:样例类
  • VertexId:Long的别名

maven工程需要下载依赖:

    <dependency>
    <groupId>org.apache.spark</groupId>
    <artifactId>spark-graphx_2.11</artifactId>
    <version>2.1.1</version>
    </dependency>
import org.apache.spark.graphx.{
   Edge, Graph}
import org.apache.spark.rdd.RDD
import org.apache.spark.{
   SparkConf, SparkContext}

object GraphxDemo1 {
   
  def main(args: Array[String]): Unit = {
   
    val conf :SparkConf= new SparkConf().setAppName("graphxDemo1").setMaster("local[2]")
    val sc = SparkContext.getOrCreate(conf)

    //创建vertices顶点rdd,(1L,1)中的1L代表顶点,1代表该顶点的属性
    val vd:RDD[(Long,Int)]=sc.makeRDD(Seq((1L,1),(2L,2),(3L,3)))

    //创建edges边rdd,(Edge(1L,2L,1)中的1L和2L代表顶点,1代表两顶点间的关系
    val ed:RDD[Edge[Int]]=sc.makeRDD(Seq(Edge(1L,2L,1),Edge(2L,3L,2)))

    //创建graph对象
    val graph=Graph(vd,ed)

    //获取graph图对象的顶点信息
    graph.vertices.collect.foreach(println)
    graph.vertices.foreach(x=>println(s"${x._1}-->${x._2}"))
    //获取graph图对象的边信息
    graph.edges.collect.foreach(println)
    graph.edges.foreach(x=>println(s"src:${x.srcId},dst:${x.dstId},attr:${x.attr}"))
    //获取顶点和边的整体信息
    graph.triplets.collect.foreach(println)
  }
}
/*
(2,2)
(1,1)
(3,3)
1-->1
3-->3
2-->2
Edge(1,2,1)
Edge(2,3,2)
src:1,dst:2,attr:1
src:2,dst:3,attr:2
((1,1),(2,2),1)
((2,2),(3,3),2)
*/

关于vertices、edges、triplets所表示的含义如下图:
在这里插入图片描述

Spark shell需要导入Spark Graph包

//导入Spark Graph包
scala> import org.apache.spark.graphx._

//通过文件加载
followers.txt内容是
2 3
1 4
3 2
4 3

scala> val graphLoad=GraphLoader.edgeListFile(sc,"file:///root/test/followers.txt")
graphLoad: org.apache.spark.graphx.Graph[Int,Int] = org.apache.spark.graphx.impl.GraphImpl@6d0c8cd0

scala> graphLoad.vertices.collect
res6: Array[(org.apache.spark.graphx.VertexId, Int)] = Array((4,1), (1,1), (3,1), (2,1))

scala> graphLoad.edges.collect
res7: Array[org.apache.spark.graphx.Edge[Int]] = Array(Edge(1,4,1), Edge(2,3,1), Edge(3,2,1), Edge(4,3,1))

scala> graphLoad.triplets.collect
res8: Array[org.apache.spark.graphx.EdgeTriplet[Int,Int]] = Array(((1,1),(4,1),1), ((2,1),(3,1),1), ((3,1),(2,1),1), ((4,1),(3,1),1))

属性图应用示例:构建用户合作关系属性图

  • 顶点属性:用户名、职业
  • 边属性:合作关系
    在这里插入图片描述
import org.apache.spark.graphx.{
   Edge, Graph}
import org.apache.spark.rdd.RDD
import org.apache.spark.{
   SparkConf, SparkContext}

object GraphDemo2 {
   
  def main(args: Array[String]): Unit = {
   
    val conf = new SparkConf().setMaster("local[1]").setAppName("graphDemo2")

    val sc = SparkContext.getOrCreate(conf)

    val user:RDD[(Long,(String,String))] = sc.parallelize(Array((3L,("rxin","student")),(7L,("jgonzal","postdoc")),(5L,("franklin","professor")),(2L,("istoica","professor"))))

    val relationship:RDD[Edge[String]]=sc.parallelize(Array(Edge(3L,7L,"Collaborator"),Edge(5L,3L,"Advisor"),Edge(2L,5L,"Colleague"),Edge(5L,7L,"PI")))

    val graphUser=Graph(user,relationship)

    graphUser.vertices.collect.foreach(println)
    graphUser.edges.collect.foreach(println)
    graphUser.triplets.collect.foreach(println)
  }
}
/*
(3,(rxin,student))
(7,(jgonzal,postdoc))
(5,(franklin,professor))
(2,(istoica,professor))
Edge(2,5,Colleague)
Edge(3,7,Collaborator)
Edge(5,3,Advisor)
Edge(5,7,PI)
((2,(istoica,professor)),(5,(franklin,professor)),Colleague)
((3,(rxin,student)),(7,(jgonzal,postdoc)),Collaborator)
((5,(franklin,professor)),(3,(rxin,student)),Advisor)
((5,(franklin,professor)),(7,(jgonzal,postdoc)),PI)
*/

属性图应用示例:

  • 构建用户社交网络关系
    • 顶点:用户名、年龄
    • 边:打call次数
  • 找出大于30岁的用户
  • 假设打call超过5次,表示真爱。请找出他(她)们
    在这里插入图片描述
import org.apache.spark.graphx.{
   Edge, EdgeTriplet, Graph}
import org.apache.spark.rdd.RDD
import org.apache.spark.{
   SparkConf, SparkContext}

object GraphDemo3 {
   
  def main(args: Array[String]): Unit = {
   
    val conf = new SparkConf().setMaster("local[1]").setAppName("graphDemo3")

    val sc = SparkContext.getOrCreate(conf)
    //构建用户社交网络关系
    val user:RDD[(Long,(String,Int))]  = sc.parallelize(
      Array(
        (1L, ("Alice", 28)),
        (2L, ("Bob", 27)),
        (3L, ("Charlie", 65)),
        (4L, ("David", 42)),
        (5L, ("Ed", 55)),
        (6L, ("Fran", 50))
      ))

    val userCall:RDD[Edge[Int]] = sc.parallelize(
      Array(
        Edge(2L, 1L, 7
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值