17周期末考试 

重点从第五章 scala语言开始

比如:映射(匿名函数)

dcc2854a71cd438386e9792fcb07ecfb.png

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 类创建图对象,并将 usersrelationships 和 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)

c24c855420cd43e0af4499e5a83f122d.png

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)

b681716f0bf545d9977d1e1c6fae7186.png

 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)

 5451042714cc4f919d3a7ed05a615a27.png

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) 

实训项目:《平凡的世界》中部分人物关系图分析

  1. 开发本地项目

创建Idea项目(方法见实验8)

下载第三方库GraphStream和BreezeViz,解压GraphStream中的core和ui压缩文件中所有的文件,包括其中所有的包

建立stylesheet.css

代码:P251

  1. 使用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"

7b1db0a8225047fa844caf7116a7e518.png

ps:注意引用库(模块设置) 

df51157f007046b491b415684a98e22e.png

db2f791084bd4f3d91f4331dd39be9c6.png

代码内容:

491a3731f5c54e50835f4f358ee0541f.png

d869b4c243b344519fa58ce84aa1c965.png

 运行结果:

9cc17dc1f2a04876a474e98f2664d64c.png

Logo

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

更多推荐