Hadoop+Spark大数据技术 实验11 Spark 图
17周期末考试重点从第五章 scala语言开始比如:映射(匿名函数)
17周期末考试
重点从第五章 scala语言开始
比如:映射(匿名函数)
11.3GraphX属性图的创建
11.3.1创建属性图
import org.apache.spark.graphx._
import org.apache.spark.rdd.RDD
//创建一个顶点集的RDD
val users: RDD[(VertexId ,(String,String))] = sc.parallelize(
Array(
(3L,("rxin","student")),
(7L,("jgonzal","postdoc")),
(5L,("franklin","prof")),
(2L,("istoica","prof")),
))
//创建一个边集的RDD
val relationships:RDD[Edge[String]] = sc.parallelize(Array(
Edge(3L,7L,"collab"),
Edge(5L,3L,"advisor"),
Edge(2L,5L,"colleague"),
Edge(5L,7L,"pi"),
))
//定义边中用户缺失时的默认(缺失)用户,
val defaultuser = ("John Doe" , "Missing")
//使用users和relationships两个RDD实例化Graph类建立一个Graph对象
val graph = Graph(users, relationships , defaultuser)
//查看图的顶点信息
graph.vertices.collect.foreach(println)
graph.edges.collect.foreach(println)
代码解释:
导入必要的库:
import org.apache.spark.graphx._
:导入 GraphX 库,提供图数据结构和操作。import org.apache.spark.rdd.RDD
:导入 RDD 库,提供弹性分布式数据集。创建顶点集 RDD:
val users: RDD[(VertexId, (String, String))]
:声明一个名为users
的 RDD,它包含顶点信息。每个顶点由一个VertexId
(长整型)和一个元组(String, String)
表示,元组包含顶点的姓名和角色。sc.parallelize(Array(...))
:使用 SparkContext 的parallelize
方法将一个数组转换为 RDD。数组包含四个顶点信息,分别为:(3L, ("rxin", "student"))
(7L, ("jgonzal", "postdoc"))
(5L, ("franklin", "prof"))
(2L, ("istoica", "prof"))
创建边集 RDD:
val relationships:RDD[Edge[String]]
:声明一个名为relationships
的 RDD,它包含边信息。每个边由一个Edge
对象表示,包含两个顶点 ID 和一个字符串类型的属性(关系类型)。sc.parallelize(Array(...))
:使用 SparkContext 的parallelize
方法将一个数组转换为 RDD。数组包含四条边信息,分别为:Edge(3L, 7L, "collab")
Edge(5L, 3L, "advisor")
Edge(2L, 5L, "colleague")
Edge(5L, 7L, "pi")
定义默认用户:
val defaultuser = ("John Doe", "Missing")
:定义一个名为defaultuser
的元组,作为边中用户缺失时的默认值。创建 Graph 对象:
val graph = Graph(users, relationships, defaultuser)
:使用Graph
类创建图对象,并将users
、relationships
和defaultuser
作为参数传入。查看图的顶点信息:
graph.vertices.collect.foreach(println)
:使用vertices
属性获取图的顶点集,并使用collect
方法将其转换为本地数组,最后使用foreach
方法打印每个顶点信息。查看图的边信息:
graph.edges.collect.foreach(println)
:使用edges
属性获取图的边集,并使用collect
方法将其转换为本地数组,最后使用foreach
方法打印每个边信息。运行结果:
(3,rxin,student) (7,jgonzal,postdoc) (5,franklin,prof) (2,istoica,prof) Edge(3,7,collab) Edge(5,3,advisor) Edge(2,5,colleague) Edge(5,7,pi)
11.3.2使用边集合的RDD创建属性图
//读取本地文件创建属性图
val recordRDD: RDD[String] = sc.textFile("edges .txt")
val EdgeRDD = recordRDD.map{
x =>val fields = x.split(" ");
Edge(
fields(0).toLong,
fields(1).toLong,
fields(2)
)
}
//使用EdgeRDD实例化Graph类建立一个Graph对象
val graphInfo = Graph.fromEdges(EdgeRDD,"VerDefaultAttr")
//查看属性图的顶点信息
graphInfo.vertices.collect.foreach(println)
//查看属性图的边信息
graphInfo.edges.collect.foreach(println)
11.3.3使用边的两个顶点的ID所组成的二元组RDD创建属性图
val recordRDD: RDD[String] = sc.textFile("edges.txt")
//创建源点ID和目的点ID二元组集合的RDD
val EdgeTupleRDD = recordRDD.map{
x=> val fields = x.split("");
(fields(0).toLong,fields(1).toLong)
}
//使用EdgeTupleRDD实例化Graph类建立一个Graph对象
val graph_fromEdgeTuples = Graph.fromEdgeTuples(EdgeTupleRDD,168L)
graph_fromEdgeTuples.vertices.collect.foreach(println)
graph_fromEdgeTuples.edges.collect.foreach(println)
11.4属性图操作
import org.apache.spark.graphx._
import org.apache.spark.rdd.RDD
//创建一个顶点集的RDD,VertexId是Long 类型数据,顶点属性是二元组
val users:RDD[(VertexId,(String, Int))]=sc.parallelize(Array(
(1L,("非菲",22)),
(2L,("乔乔",17)),
(3L,("王强",19)),
(4L,("王刚",21)),
(5L,("李倩",20)),
(6L,("林锋",25))
))
//创建一个边集的RDD
val relationships: RDD[Edge[Int]] = sc.parallelize(Array(
Edge(1L, 3L, 15),
Edge(2L, 1L, 10),
Edge(2L, 3L, 21),
Edge(2L, 4L, 22),
Edge(3L, 6L, 10),
Edge(4L, 5L, 17),
Edge(5L, 6L, 20)
))
//定义边中用户缺失时的默认(缺失)用户
val defaultUser =("某某",18)
//使用users 和relationships 两个RDD实例化Graph 类,建立一个Graph 对象
val userGraph = Graph(users,relationships,defaultUser)
11.4.1图的属性操作
下面通过图的属性获取属性图的边的数量、居性图的顶点的数量、属性图的所有顶点的入度、属性图的所有顶点的出度,以及属性图的所有项点的入度与出度之和。
1. 获取边的数量
//获取属性图的边的数量
scala> userGraph.numEdges
resl: Long = 7
userGraph
是定义的属性图对象。numEdges
是 GraphX 中Graph
对象的一个属性,用于返回图中边的数量。- 返回值类型为
Long
,因为边的数量可能很大。
2. 获取顶点的数量
userGraph.numVertices
res2:Long = 6//获取顶点的数量
numVertices
是 GraphX 中Graph
对象的一个属性,用于返回图中顶点的数量。- 返回值类型为
Long
,因为顶点的数量可能很大。
入度 (In-degree)
- 定义: 指向一个顶点的边的数量。
- 形象解释: 可以理解为有多少条边 "指向" 某个顶点。
- 例子: 想象一个社交网络,一个人拥有 5 个朋友,那么这个人就拥有 5 个入度,因为有 5 条边指向他。
出度 (Out-degree)
- 定义: 从一个顶点发出的边的数量。
- 形象解释: 可以理解为有多少条边 "从" 某个顶点 "发出"。
- 例子: 继续社交网络的例子,如果这个人主动添加了 3 个朋友,那么他的出度就是 3,因为有 3 条边从他发出。
总结
- 入度和出度是描述图中顶点连接关系的重要指标。
- 入度表示一个顶点被其他顶点连接的程度,反映了这个顶点在图中的 "受欢迎程度"。
- 出度表示一个顶点主动连接其他顶点的程度,反映了这个顶点在图中的 "主动性"。
3. 获取所有顶点的入度
userGraph.inDegrees.collect.foreach(println)
(4,1) (1,1) (5,1) (6,2) (3,2)
userGraph.inDegrees
:获取图中所有顶点的入度,返回值类型为VertexRDD[Int]
。VertexRDD
是 GraphX 中用来表示顶点数据的 RDD。collect
:将VertexRDD
中的元素收集到一个本地数组中。foreach(println)
:遍历本地数组,并打印每个顶点及其入度信息。- 输出结果:每个顶点及其入度,例如
(1,1)
表示顶点 1 的入度为 1。
4. 获取所有顶点的出度
userGraph.outDegrees.collect.foreach(println)
(4,1) (1,1) (5,1) (2,3) (3,1)
userGraph.outDegrees
:获取图中所有顶点的出度,返回值类型为VertexRDD[Int]
。collect
:将VertexRDD
中的元素收集到一个本地数组中。foreach(println)
:遍历本地数组,并打印每个顶点及其出度信息。- 输出结果:每个顶点及其出度,例如
(1,2)
表示顶点 1 的出度为 2。
5. 获取所有顶点的入度和出度之和
userGraph.degrees.collect.foreach(x => print(x + ","))
(4,2),(1,2),(5,2),(6,2),(2,3),(3,3),
userGraph.degrees
:获取图中所有顶点的入度和出度之和,返回值类型为VertexRDD[Int]
。collect
:将VertexRDD
中的元素收集到一个本地数组中。foreach(x => print(x + ","))
:遍历本地数组,并打印每个顶点及其入度和出度之和。- 输出结果:每个顶点及其入度和出度之和,例如
(4,2)
表示顶点 4 的入度和出度之和为 2 + 2 = 4。
11.4.2图的视图操作
1.顶点视图
//输出所有顶点
userGraph.vertices.collect.foreach(println)
(4,(王刚,21)) (1,(非菲,22)) (5,(李倩,20)) (6,(林锋,25)) (2,(乔乔,17)) (3,(王强,19))
//case模式匹配
userGraph.vertices.map{
case(id,(name,age)) =>
(age,name)
}.collect.foreach(println)
(21,王刚) (22,非菲) (20,李倩) (25,林锋) (17,乔乔) (19,王强)
//过滤
userGraph.vertices.filter{
case(id,(name,age)) =>
age<20
}.collect.foreach(println)
(2,(乔乔,17)) (3,(王强,19))
Selection deleted
//元组索引查看顶点信息
userGraph.vertices.map{
v => ("姓名:" + v._2._1,
"年龄:" + v._2._2,
"ID:" + v._1)
}.collect.foreach(println)
(姓名:王刚,年龄:21,ID:4) (姓名:非菲,年龄:22,ID:1) (姓名:李倩,年龄:20,ID:5) (姓名:林锋,年龄:25,ID:6) (姓名:乔乔,年龄:17,ID:2) (姓名:王强,年龄:19,ID:3)
2.边视图
//查看所有信息
userGraph.edges.collect.foreach(println)
Edge(1,3,15) Edge(2,1,10) Edge(2,3,21) Edge(2,4,22) Edge(3,6,10) Edge(4,5,17) Edge(5,6,20)
//过滤
userGraph.edges.filter{
case Edge(src,dst,attr) =>
src > dst
}.collect.foreach(println)
Edge(2,1,10)
//索引查看
userGraph.edges.map{
v => ("源点ID:" + v.srcId,
",目的点ID:" + v.dstId,
",边属性:" + v.attr)
}.collect.foreach(println)
(源点ID:1,,目的点ID:3,,边属性:15) (源点ID:2,,目的点ID:1,,边属性:10) (源点ID:2,,目的点ID:3,,边属性:21) (源点ID:2,,目的点ID:4,,边属性:22) (源点ID:3,,目的点ID:6,,边属性:10) (源点ID:4,,目的点ID:5,,边属性:17) (源点ID:5,,目的点ID:6,,边属性:20)
3.边点三元组视图
//直接查看顶点,边信息
userGraph.triplets.collect.foreach(println)
实训项目:《平凡的世界》中部分人物关系图分析
- 开发本地项目
创建Idea项目(方法见实验8)
下载第三方库GraphStream和BreezeViz,解压GraphStream中的core和ui压缩文件中所有的文件,包括其中所有的包。
建立stylesheet.css
代码:P251
- 使用sbt项目完成(可选)
build.sbt的参考内容如下:
name := "P251"
version := "0.1"
scalaVersion := "2.11.12"
libraryDependencies += "org.apache.spark" %% "spark-core" % "2.4.5"
libraryDependencies += "org.apache.spark" %% "spark-graphx" % "2.4.5"
// Graph Visualization
// https://mvnrepository.com/artifact/org.graphstream/gs-core
libraryDependencies += "org.graphstream" % "gs-core" % "1.2"
// https://mvnrepository.com/artifact/org.graphstream/gs-ui
libraryDependencies += "org.graphstream" % "gs-ui" % "1.2"
// https://mvnrepository.com/artifact/org.scalanlp/breeze_2.10
libraryDependencies += "org.scalanlp" % "breeze_2.11" % "0.12"
// https://mvnrepository.com/artifact/org.scalanlp/breeze-viz_2.11
libraryDependencies += "org.scalanlp" % "breeze-viz_2.11" % "0.12"
// https://mvnrepository.com/artifact/org.jfree/jcommon
libraryDependencies += "org.jfree" % "jcommon" % "1.0.24"
// https://mvnrepository.com/artifact/org.jfree/jfreechart
libraryDependencies += "org.jfree" % "jfreechart" % "1.0.19"
ps:注意引用库(模块设置)
代码内容:
运行结果:

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐
所有评论(0)