Saprk GraphX
(1)为什么需要图计算
许多大数据以大规模图或网络的形式呈现
许多非图结构的大数据,常会被转换为图模型进行分析
图数据结构很好地表达了数据之间的关联性
(2)图(Graph)的基本概念
--图是由顶点集合(vertex)及顶点间的关系集合(边edge)组成的一种网状数据结构
通常表示为二元组:Gragh=(V,E)
可以对事物之间的关系建模
--应用场景
在地图应用中寻找最短路径
社交网络关系
网页间超链接关系
(3)图的术语
顶点(Veretex)
边(Edge)
Graph=(V,E)
集合V={v1,v2,v3}
集合E={(v1,v2),(v1,v3),(v2,v3)}
(4)图的分类
有向图
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)}
有环图
包含一系列顶点连接的回路(环路)
无环图
DAG即为有向无环图
(5)度
度:一个顶点所有边的数量
出度:指从当前顶点指向其他顶点的边的数量
入度:其他顶点指向当前顶点的边的数量
例如:顶点11 出度:3 入度:2
顶点:9 出度:0 入度:2
(6)java api基础实现(用户合作关系)
package graph
import org.apache.spark.graphx.{Edge, Graph}
import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}
object Graph01 {
def main(args: Array[String]): Unit = {
val conf: SparkConf = new SparkConf().setMaster("local[*]").setAppName("graph1")
val sc = new SparkContext(conf)
//创建点的集合
val vertices: RDD[(Long, (String, String))] = sc.makeRDD(Seq((3L, ("rxin", "student")), (2L, ("istoica", "professor")), (5L, ("franklin", "professor")), (7L, ("igonzai", "postdoc"))))
//创建边的集合
val edges: RDD[Edge[String]] = sc.makeRDD(Seq(
Edge(3L, 7L, "collaborator"),
Edge(5L, 3L, "advisor"),
Edge(2L, 5L, "colleague"),
Edge(5L, 7L, "PI")
))
//创建图形
val graph: Graph[(String, String), String] = Graph(vertices, edges)
//每个顶点的入度
graph.inDegrees.foreach(println)
// (7,2)
// (3,1)
// (5,1)
//每个顶点的出度
graph.outDegrees.foreach(println)
// (5,2)
// (2,1)
// (3,1)
//每个顶点的度的集合
graph.degrees.foreach(println)
// (2,1)
// (3,2)
// (5,3)
// (7,2)
//图形的每个顶点的id和属性
graph.vertices.foreach(x=>println(x._1,x._2))
// (7,(igonzai,postdoc))
// (5,(franklin,professor))
// (2,(istoica,professor))
// (3,(rxin,student))
//图形的每条边的出发顶点的id,目的顶点的id,权重
graph.edges.foreach(x=>println(x.srcId,x.dstId,x.attr))
// (3,7,collaborator)
// (5,7,PI)
// (5,3,advisor)
// (2,5,colleague)
//图形的每条边的出发顶点的属性,目的顶点的属性,权重
graph.triplets.foreach(x=>println(x.srcAttr,x.dstAttr,x.attr))
// ((istoica,professor),(franklin,professor),colleague)
// ((franklin,professor),(igonzai,postdoc),PI)
// ((rxin,student),(igonzai,postdoc),collaborator)
// ((franklin,professor),(rxin,student),advisor)
//建立新的点,将图形的顶点的属性相加,如果新点不存在,属性不变
val newVertices: RDD[(Long, String)] = sc.makeRDD(Seq((1L, "hello"), (2L, "hello"), (3L, "hello")))
val graph2: Graph[(String, String), String] = graph.joinVertices(newVertices)((id, oldvalue, newvalue) => (oldvalue._1, oldvalue._2 + "@@" + newvalue))
graph2.vertices.foreach(x=>println(x))
// (5,(franklin,professor))
// (7,(igonzai,postdoc))
// (3,(rxin,student@@hello))
// (2,(istoica,professor@@hello))
//建立新的点,将图形的顶点的属性相加,如果新点不存在,属性加上None
val newVertices2: RDD[(Long, String)] = sc.makeRDD(Seq((1L, "hello"), (2L, "hello"), (3L, "hello")))
val graph3: Graph[(String, String), String] = graph.outerJoinVertices(newVertices2)((id, oldvalue, newvalue) => (oldvalue._1, oldvalue._2 + "##" + newvalue))
graph3.vertices.foreach(println)
// (5,(franklin,professor##None))
// (3,(rxin,student##Some(hello)))
// (7,(igonzai,postdoc##None))
// (2,(istoica,professor##Some(hello)))
}
}
(7)java api基础实现(社交网络关系)
package graph
import org.apache.spark.graphx.{Edge, Graph}
import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}
object Graph02 {
def main(args: Array[String]): Unit = {
//创建spark-context
val conf: SparkConf = new SparkConf().setMaster("local[*]").setAppName("graph2")
val sc = new SparkContext(conf)
//创建顶点
val vertices: RDD[(Long, (String, Int))] = sc.makeRDD(Seq((1L, ("Alice", 28)), (2L, ("Bob", 27)), (3L, ("Charlie", 65))
, (4L, ("David", 42)), (5L, ("ED", 55)), (6L, ("Fran", 50))))
//创建边
val edges: RDD[Edge[Int]] = sc.makeRDD(Seq(
Edge(2L, 1L, 7),
Edge(4L, 1L, 1),
Edge(2L, 4L, 2),
Edge(3L, 2L, 4),
Edge(5L, 2L, 2),
Edge(5L, 3L, 8),
Edge(3L, 6L, 3),
Edge(5L, 6L, 3)
))
//创建图
val graph: Graph[(String, Int), Int] = Graph(vertices, edges)
//找出大于30岁的用户
graph.vertices.filter(x=>x._2._2>30).foreach(x=>println(x._2._1,x._2._2))
// (Fran,50)
// (ED,55)
// (David,42)
// (Charlie,65)
// //假设打电话超过5次为真爱,请找出它们
graph.triplets.filter(x=>x.attr>5).foreach(x=>println(x.srcAttr._1,x.dstAttr._1))
// (ED,Charlie)
// (Bob,Alice)
}
}
(ED,55)
// (David,42)
// (Charlie,65)
// //假设打电话超过5次为真爱,请找出它们
graph.triplets.filter(x=>x.attr>5).foreach(x=>println(x.srcAttr._1,x.dstAttr._1))
// (ED,Charlie)
// (Bob,Alice)
}
}