【大数据分析】GraphX:基础

顶点对象与边对象

弹性分布式数据集(RDD)是构建Spark程序的基础模块,它提供了灵活、高效、并行化数据处理和容错等特性。在GraphX中,图的基础类为Graph,它包含两个RDD:一个为边RDD,另一个为顶点RDD。
在这里插入图片描述
与其他图处理系统和图数据库相比,基于图概念和图处理原语的GraphX,它的一大优势在于,既可以将底层数据看作一个完整的图,使用图概念和图处理原语;也可以将它们看作独立的边RDD和顶点RDD,使用数据并行处理原语,进行mapped、joined、transformed等操作。

在GraphX里,没必要(从某些特定顶点开始)“遍历”全图以得到想要的边和顶点。例如,对顶点属性数据进行转换可以一下子完成,而在其他图处理系统和图数据库里,类似的操作就没那么方便了,需要两步:先执行必要的查询,然后再对查询的结果顶点集执行转换操作。

可以用给定的边RDD和顶点RDD构建一个图。一旦构建好图,就可以用函数edges()和vertices()来访问边和顶点的集合。

import org.apache.spark.graphx._

val myVertices = sc.makeRDD(Array((1L, "Ann"), (2L, "Bill"),
 (3L, "Charles"), (4L, "Diane"), (5L, "Went to gym this morning")))

val myEdges = sc.makeRDD(Array(Edge(1L, 2L, "is-friends-with"),
 Edge(2L, 3L, "is-friends-with"), Edge(3L, 4L, "is-friends-with"),
 Edge(4L, 5L, "Likes-status"), Edge(3L, 5L, "Wrote-status")))

val myGraph = Graph(myVertices, myEdges)
myGraph.vertices.collect
myGraph.edges.collect

可以使用triplets()方法,根据VertexId将顶点和边联合在一起。Graph本来是将数据分开存储在对应的边RDD和顶点RDD内,triplets()函数只不过是方便地将它们联合在一起。

myGraph.triplets.collect

函数triplets()返回EdgeTriplet[VD,ED]类型的RDD,它是Edge[ED]的子类,并包含边的源顶点和目标顶点的引用。
EdgeTriplet的常用成员属性

字段描述
Attr边的属性数据
srcId边的源顶点的ID
srcAttr边的源顶点的属性数据
dstId边的目标顶点的Id
dstAttr边的属性数据
EdgeTriplet类提供了访问边(以及边属性数据)以及源顶点和目标顶点属性数据的方法。GraphX可以便捷地访问边和顶点数据,让图处理任务更简单易用。
在这里插入图片描述

mapping操作

GraphX Map/Reduce操作中最有价值的函数是aggregateMessages()(代替已被废弃的mapReduceTriplets函数)。在实际使用这个函数前,首先让我们来看看更简单的mapTriplets()函数,这也会引出GraphX的另一个重要概念。本书中涉及的很多转换操作都会从原来的图生成一个新图。虽然我们也可以自己对边和顶点转换来创建一个新图,这两者的最终结果或许是一致的,但这样就不能利用GraphX提供的底层优化功能了。

简单的图转换

在边属性上增加布尔类型的属性来表示一个条件限制,1、属性中包含“is-friends-with”的边;2、边所关系的源顶点属性中包含a的。
在边属性上增加布尔类型的属性来表示一个条件限制

myGraph.mapTriplets(t => (t.attr, t.attr=="is-friends-with" &&
 t.srcAttr.toLowerCase.contains("a"))).triplets.collect

在这里插入图片描述
尽管mapTriplets()有两个可选参数,但这里我们只用了第一个参数。这个参数是一个匿名函数,它传入一个EdgeTriplet对象作为输入参数,返回一个包含二元组(String,Boolean)的Edge类型。与允许转变Edge类的mapTriplets()类似,函数mapVertices()允许我们直接转变Vertex类。

Map/Reduce

很多图处理任务需要聚集从周围本地邻居顶点发出的消息。这里的邻居指的是顶点周围直接相关联的边和顶点。
统计每个顶点的“出度”——即对于每个顶点而言,离开该顶点的边的条数。

myGraph.aggregateMessages[Int](_.sendToSrc(1), _ + _).collect

这里仅仅需要aggregateMessages函数就可以完成任务

def aggregateMessage[Msg](sendMsg:EdgeContext[VD,ED,Msg]=>Unit,
	mergeMsg:(Msg,Msg)=>Msg
):VertexRDD[Msg]

aggregateMessages的两个参数是sendMsg和mergeMsg,它们提供了转换和聚合的能力。

sendMsg

sendMsg函数以EdgeContext作为输入参数,没有返回值。EdgeContext接口的实现类提供了两个Msg的sendMsg函数。

sendToSrc:将Msg类型的消息发送给源顶点。
sendToDst:将Msg类型的消息发送给目标顶点。

sendToSrc是针对源顶点的统计,而sendToDst则是针对目标顶点的统计。在sendMsg方法内部,参数EdgeContext用于检查边、源顶点、目标顶点三者的属性值。在这个例子中,因为需要计算每个顶点发出的边数,每次累加的值为1,所以传入的消息是1。(可以感性理解成,这个1是沿着边给到顶点的,一个顶点有多少个边,就有多少1)

mergeMsg

每个顶点收到的所有消息都会被聚集起来传递给mergeMsg函数。这个函数定义了如何将顶点收到的所有消息转换成我们需要的结果。在示例代码中,我们将所有发给源顶点的数字1累加起来得出边的总数。这就是匿名函数" _ "使用+操作完成的。

在每个顶点上应用mergeMsg函数最终会返回一个VertexRDD[Int]对象。VertexRDD是一个包含了二元组的RDD,包括了顶点的ID以及该顶点的mergeMsg操作的结果。需要注意的一点是,由于顶点#5不含有任何出边,它接收不到任何消息,所以它不会出现在结果VertexRDD中。

RDD的join()操作用于匹配VertexId与顶点数据

myGraph.aggregateMessages[Int](_.sendToSrc(1),
 _ + _).join(myGraph.vertices).collect

上面的做法看起来还是有点烦琐。因为其实后面用不到这些VertexId,所以可以使用RDD的map()函数去掉它们,可以使用二元组的swap()方法交换两个元素的顺序,将可读的顶点名放在出度值之前使得输出更为美观。

myGraph.aggregateMessages[Int](_.sendToSrc(1),
 _ + _).join(myGraph.vertices).map(_._2.swap).collect

迭代的Map/Reduce

大多数的算法都包含多次迭代。aggregateMessages可用于这类算法,其仅需要基于邻边和顶点发送过来的消息进而不断更新每个顶点的状态。例如:为每个顶点标记上离它最远的根顶点的距离。

首先我们对aggregateMessages会调用到的sendMsg和mergeMsg进行定义。在这里不把sendMsg和mergeMsg作为匿名函数传给aggregateMessages函数,而是显式地定义sendMsg和mergeMsg函数。

在函数式编程中实现迭代通常采用递归的方式,所以接下来定义一个用于递归的辅助函数propagateEdgeCount,它会持续调用aggregateMessages。

//这个方法会在没条边上调用
def sendMsg(ec: EdgeContext[Int,String,Int]): Unit = {
  ec.sendToDst(ec.srcAttr+1)
}

def mergeMsg(a: Int, b: Int): Int = {
  math.max(a,b)
}

def propagateEdgeCount(g:Graph[Int,String]):Graph[Int,String] = {    
  val verts = g.aggregateMessages[Int](sendMsg, mergeMsg)
  val g2 = Graph(verts, g.edges)
  val check = g2.vertices.join(g.vertices).
       map(x => x._2._1-x._2._2).
       reduce(_ + _)
  if (check > 0)
    propagateEdgeCount(g2)
  else
    g
}

//创建边信息
val myEdges = sc.parallelize(Array(
  Edge(1L, 2L, "friends"),
  Edge(2L, 3L, "friends"),
  Edge(3L, 4L, "colleagues"),
  Edge(3L, 5L, "friends"),
  Edge(4L, 5L, "colleagues")
))
val myGraph = Graph(myVertices, myEdges)
//设置顶点属性, 将所有顶点的属性初始化为 0
val initGraph = myGraph.mapVertices((_,_) => 0)
propagateEdgeCount(initGraph).vertices.collect.foreach(println(_))

整个递归过程示例图如下所示:
在这里插入图片描述

生成图

可使用GraphGenerators对象来生成一些随机图。当需要快速验证一些图函数或图算法时,这种方法十分有效。其中,generateRandomEdges()是生成图函数的一个辅助函数;单独使用它并不是那么有效,因为它会接收一个单一的顶点ID作为参数输入,而接下来所有生成的边都会跟这个顶点有关。

确定的图

网格图

网格图的顶点和边符合特定的模式,就像是在一个二维的网格或矩阵中。每一个顶点都用它在网格中行和列的位置作为标签(例如,左上顶点的标签为(0,0))。每个顶点都和它上、下、左、右的直接邻居相连。

val pw = new java.io.PrintWriter("gridGraph.gexf")
pw.write(toGexf(util.GraphGenerators.gridGraph(sc, 4, 4)))
pw.close

在这里插入图片描述

星形图

星形图指的是有一个顶点通过边与所有其他顶点相连,除此之外图中不存在其他边。

val pw = new java.io.PrintWriter("starGraph.gexf")
pw.write(toGexf(util.GraphGenerators.starGraph(sc, 8)))
pw.close

在这里插入图片描述

随机图

GraphX提供了两种随机生成图的方法:一个是单步算法(称为对数正态算法),它将特定数量的边与各个顶点关联起来;另一个是多步算法(称为R-Mat算法),它会生成与现实世界比较相近的图。

对数正态图

对数正态图(log normal graph)关注的是生成图的每个顶点的出度值分布。它保证在对所有的出度值绘制直方图时,你可以看到一个对数正态分布的形状(高斯钟形曲线),这意味着log(d)服从正态分布(d代表顶点的度值)。

val logNormalGraph = util.GraphGenerators.logNormalGraph(sc, 15)
val pw = new java.io.PrintWriter("logNormalGraph.gexf")
pw.write(toGexf(logNormalGraph))
pw.close
logNormalGraph.aggregateMessages[Int](
    _.sendToSrc(1), _ + _).map(_._2).collect.sorted

基于程序化流程的:R-MAT图

R-MAT,代表递归矩阵,用于模拟典型的社交网络架构。与之前的基于度值的logNormalGraph()函数相反,rmatGraph()进行“程序化”的过程。

val pw = new java.io.PrintWriter("rmatGraph.gexf")
pw.write(toGexf(util.GraphGenerators.rmatGraph(sc, 32, 60)))
pw.close

在这里插入图片描述

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
DOI:10.16525/j.cnki.14-1362/n.2019.10.31 总第 184 期 2019 年第10 期 Total of 184 No.10, 2019 大数据 收稿日期: 2019-08-16 第一作者简介: 林海 (1989—) , 男, 本科, 研究方向为飞行 教育。 基于大数据下的 Spark 快速大数据分析 林 海, 王 强, 李英震 (空军航空大学初级飞行训练基地二团, 黑龙江 哈尔滨 150100) 摘 要: 在数据大爆炸的时代, 随着数据量的激增, 如何更快速地处理、 使用这些规模大、 复杂度高的数据成为 迫在眉睫的问题。阐述了 Spark 的五大组件,研究了 Spark 数据处理应用和运行架构。Spark 通过优化传统的 MapReduce 模型来满足之前 HDFS 以及 MapReduce 无法解决的问题, 大大提高了效率, 为处理流式数据以及 其他需求提供了捷径。 关键词: 大数据; 数据分析; 计算; 数据处理 中分类号: TP311 文献标识码: A 文章编号: 2095-0748 (2019) 10-0075-02 现代工业经济和信息化 Modern IndustrialEconomy and Informationization 引言 随着科学技术和社会经济的高速发展, 我们已经 处于一个数据大爆炸的时代, 手机、 ipad 以及其他的 物联网设备每分每秒都会产生大量的全新数据, 这 些数据不仅数量大,而且更加复杂,来源也越来越 广。 据科学家预测, 到 2020 年, 将会有 600 多亿台的 互联网设备产生 Zeta 级的数据, 所以如何更加合理 快速地处理并且使用这些规模大、复杂度高的数据 成为我们迫在眉睫需要解决的问题。 随着数据量的快速增长,以及一些公司对数据 进行实时计算和实时处理的要求,传统的 MapRe- duce 模型已经无法满足这些要求, 而且更加重要的是 MapReduce 在进行 Shuffle 时会产生大量的 I/O, 使 得效率变低。 Spark 的出现扩展了传统的 MapReduce 模型, 不但能提供更多更加高效的计算模型, 还能够 适用于多种不同的分布式平台场景上。同时 Spark 还可以让使用者们简单而低消耗地将各种处理流程 整合到一起,这样既满足了对实时计算以及实时处 理的要求, 还减轻了对各种平台分别管理的负担[1]。 1 Spark 的五大组件 在 spark Core 中实现了 Spark 的一些基础的功 能, 例如进行内存的管理、 进行错误的恢复、 对任务 的调度、 与存储系统进行交互等功能。 它还包含了对 弹性分布式数据集的 API 定义。 Spark SQL 是被用来对结构化数据进行操作 的程序包, 它支持多种数据源, 例如 Hive 表、 JSON、 Parquet 等, 还可以使用 HQL 来进行数据的查询。 Spark Streaming 能够对实时的数据进行流式计 算。 它具有准时的特点, 同时提供离散化流数据的高 级抽象概念, 以此来表示连续的数据流。 离散流是可 以来自 Flume、 Kafka 等输入源的输入数据流来创 建, 进行批处理, 时间一般是秒级。 MLib 是 Spark 提供的一个常见的机器学习功能 的程序库, 它提供了许许多多的机器学习算法, 这些 算法中包括了回归、 聚类、 分类、 协同过滤、 数据导 入、 模型评估等功能。 Graphx 是能够进行并行操作的计算,可以用 来操作的程序库。 2 Spark 数据处理应用 众所周知因为 MapReduce 在交互计算以及迭 代计算任务上的效率比较低,所以 Spark 出现了, Spark 的出现使得交互式查询以及迭代计算效率大 大增加,不但如此它还支持高效的容错机制和内存 式存储。Spark 不仅仅能够将 HDFS (分布式文件系 统) 上面的文件读取为分布式数据集, 还支持本地文 件、 Hive、 HBase 等。 每一个 Spark 应用都会由一个驱动 器程序 (Driver Program) 来发起集群上的并行操作[2]。 3 Spark 的运行架构 在 HDFS 的环境下, Spark 采取的是 Master/Slave, 即主从架构,也就是由一个主节点来负责中央的协 调, 调度其他每个分布式节点, 其中负责中央协调的 节点就称为驱动器节点,也就是我们所说的 Driver 第 9 卷 现代工业经济和信息化 xdgyjjxxhx@163.com (上接第 74 页) Application of Big Data in Human Resource Management Wang Xiaoli (Shanxi Provincial Pers
### 回答1: Python是一种非常流行的编程语言,被广泛用于数据科学领域。它提供了许多库和工具,使数据分析和可视化变得更加简单和方便。下面列举几个Python数据分析和可视化实例的源代码: 1. 使用Matplotlib库绘制简单的折线: ```python import matplotlib.pyplot as plt x = [1, 2, 3, 4, 5] y = [2, 4, 6, 8, 10] plt.plot(x, y) plt.xlabel('X-axis') plt.ylabel('Y-axis') plt.title('Simple Line Graph') plt.show() ``` 2. 使用Seaborn库绘制带有标签的散点: ```python import seaborn as sns import pandas as pd df = pd.read_csv('data.csv', delimiter=',') sns.scatterplot(x='x_axis_data', y='y_axis_data', hue='label_data', data=df) plt.title('Labelled Scatterplot') plt.show() ``` 3. 使用Pandas库绘制柱状: ```python import pandas as pd import matplotlib.pyplot as plt df = pd.read_csv('data.csv', delimiter=',') df.plot(kind='bar', x='categories', y='values') plt.title('Bar Chart') plt.xlabel('Categories') plt.ylabel('Values') plt.show() ``` 以上三个例子仅是Python数据分析和可视化中的冰山一角,实际上还有很多其他的技术和工具可以应用到数据的可视化中。通过这些可视化的方式,能够更直观地展示数据,帮助我们更好地了解和分析数据,为我们制定决策提供更准确的依据。 ### 回答2: Python数据分析可视化是目前常见的数据分析方法之一,通过将数据用表、形等形式展示出来,可以更加直观地了解数据的特点、趋势和异常情况等。 对于Python数据分析可视化实例可以参考如下代码: 首先导入所需的库 ```python import matplotlib.pyplot as plt import pandas as pd import seaborn as sns ``` 然后读取数据 ```python df = pd.read_csv('data.csv') ``` 接下来通过matplotlib绘制散点 ```python plt.scatter(df['x'], df['y']) plt.title('Scatter Plot') plt.xlabel('x') plt.ylabel('y') plt.show() ``` 在此基础上进行可视化分析,比如加入颜色和规格化等信息 ```python sns.scatterplot(df['x'], df['y'], hue=df['color'], style=df['symbol'], s=df['size']) plt.title('Scatter Plot') plt.xlabel('x') plt.ylabel('y') plt.show() ``` 使用seaborn实现这样的代码可以更加灵活直观地展示数据分析结果,让人们可以快速将数据分析思路转化为可视化结果。 综上,Python数据分析可视化实例可以通过利用常见的库和工具进行代码实现,这不仅简化了数据分析的流程,也让数据分析结果得到更加直观清晰的展示。 ### 回答3: Python数据分析可视化实例源码是指采用Python语言编写的数据分析程序,并且具有可视化效果。这些源码可以通过开源社区、GitHub等途径获取,也可以在机器学习和数据分析相关的书籍中找到。下面以Python数据分析常用的matplotlib库为例,简单介绍其中的源码: 一、散点 散点是一种用于研究两个变量之间关系的形。在Python中,使用matplotlib库中的scatter函数可以绘制散点。下面是一个简单的示例代码: import matplotlib.pyplot as plt x = [1, 2, 3, 4, 5] y = [5, 4, 3, 2, 1] plt.scatter(x, y) plt.show() 该代码可以生成一张包含5个散点的散点。 二、折线 折线是一种用于表示连续数据的形,它是一条或多条曲线沿着水平轴绘制,其中横坐标通常表示时间或其他连续变量。在Python中,使用matplotlib库中的plot函数可以绘制折线。下面是一个简单的示例代码: import matplotlib.pyplot as plt x = [1, 2, 3, 4, 5] y = [5, 4, 3, 2, 1] plt.plot(x, y) plt.show() 该代码可以生成一张包含5个点的折线。 三、直方 直方是一种用于表示频率分布的形,通常用于展示数据的分布情况。在Python中,使用matplotlib库中的hist函数可以绘制直方。下面是一个简单的示例代码: import matplotlib.pyplot as plt data = [1, 2, 3, 4, 5] plt.hist(data, bins=5) plt.show() 该代码可以生成一张包含5个条状的直方,每个条状表示一个数据区间的数量。 以上三种数据可视化方式只是Python数据分析中的冰山一角,在实际应用中还有很多数据可视化技术,可以灵活运用,以更好地从数据中获取价值信息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值