Spark GraphX學習(一)Connected Components算法

       現實生活中存在各種各樣的網絡,諸如人際關係網、交易網、運輸網等等。對這些網絡進行社區發現具有極大的意義,如在人際關係網中,可以發現出具有不同興趣、背景的社會團體,方便進行不同的宣傳策略。本文采用Spark GraphX三大算法之一的Connected Components算法實現社交網絡中的社區發現。


1.Spark GraphX基礎知識


1.1Graph

       Spark中屬性圖是由VertexRDDEdgeRDD兩個參數構成的。其中,每個vertex由一個唯一的64位長的標識符(VertexId)作爲key。同時,屬性圖也和RDD一樣,是不可變的、分佈式的、可容錯的。屬性圖Graph的定義如下:

abstract class Graph[VD, ED]{  
    val vertices: VertexRDD[VD]  
    val edges: EdgeRDD[ED  
    val triplets: RDD[EdgeTriplet[VD, ED]]]  
} 

Graph中包含了三個屬性頂點集、邊集、triplets集(三元組)。可以用圖形象的表示爲: 


· Vertices:由VertexIdLong類型)、attribute(屬性描述或距離)構成。如,(3L, ("San Francisco", "CA")),(1L, 10

· Edges:由srcId(起始節點VertexId)、dstId(終止節點VertexId)、attribute(邊的權值)構成。如,Edge(1L, 2L, 20)

· Triplets:由srcIdsrcAttr(起始Vertex)和dstIddstAttr(終止Vertex),以及attr構成。如,((1, (Santa Clara, CA)), (2, (Fremont, CA)), 20)

1.2GraphLoader

       GraphLoader.edgeListFile:Graph[Int,Int]) 提供了一個方式從磁盤上的邊列表中加載一個圖。它解析如下形式(源頂點ID,目標頂點ID)的連接表:

2 1
4 1
1 2

它從指定的邊創建一個圖,自動地創建邊提及的所有頂點。頂點和邊的屬性默認都是1


2.Connected Components算法


       Connected Components連通體算法用id標註圖中每個連通體,將連通體中序號最小的頂點的id作爲連通體的id。如果在圖G中,任意2個頂點之間都存在路徑,那麼稱G爲連通圖否則稱該圖爲非連通圖,則其中的極大連通子圖稱爲連通體,如下圖所示,該圖中有兩個連通體


3.Spark GraphX實現社區發現


介紹完以上的基本概念,我們可以使用Spark GraphX實現社區網絡的社區發現。

有兩個輸入文件:

followers.txt (起點id,終點id)

4 1
1 2
6 3
7 3
7 6
6 7
3 7

users.txt (id,first name,full name)

1,BarackObama,Barack Obama
2,ladygaga,Goddess of Love
3,jeresig,John Resig
4,justinbieber,Justin Bieber
6,matei_zaharia,Matei Zaharia
7,odersky,Martin Odersky
8,anonsys
代碼實現:

import org.apache.spark.graphx.{Graph, GraphLoader, VertexId, VertexRDD}
import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}

object GraphTest {
  def main(args: Array[String]): Unit = {
    val conf: SparkConf = new SparkConf().setAppName(this.getClass.getSimpleName).setMaster("local")
    val sc: SparkContext = new SparkContext(conf)
    //讀取followers.txt文件創建圖
    val graph: Graph[Int, Int] = GraphLoader.edgeListFile(sc,"F:\\followers.txt")
    //計算連通體
    val components: Graph[VertexId, Int] = graph.connectedComponents()
    val vertices: VertexRDD[VertexId] = components.vertices
    /**
      * vertices:
      * (4,1)
      * (1,1)
      * (6,3)
      * (3,3)
      * (7,3)
      * (2,1)
      * 是一個tuple類型,key分別爲所有的頂點id,value爲key所在的連通體id(連通體中頂點id最小值)
      */
    //讀取users.txt文件轉化爲(key,value)形式
    val users: RDD[(VertexId, String)] = sc.textFile("F:\\users.txt").map(line => {
      val fields: Array[String] = line.split(",")
      (fields(0).toLong, fields(1))
    })
    /**
      * users:
      * (1,BarackObama)
      * (2,ladygaga)
      * (3,jeresig)
      * (4,justinbieber)
      * (6,matei_zaharia)
      * (7,odersky)
      * (8,anonsys)
      */
    users.join(vertices).map{
      case(id,(username,vertices))=>(vertices,username)
    }.groupByKey().map(t=>{
      t._1+"->"+t._2.mkString(",")
    }).foreach(println(_))
    /**
      * 得到結果爲:
      * 1->justinbieber,BarackObama,ladygaga
      * 3->matei_zaharia,jeresig,odersky
      */
  }

}

最終計算得到這個關係網絡有兩個社區。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章