Spark操作—aggregate、aggregateByKey详解
https://blog.csdn.net/u013514928/article/details/56680825
1. aggregate函数
将每个分区里面的元素进行聚合,然后用combine函数将每个分区的结果和初始值(zeroValue)进行combine操作。这个函数最终返回的类型不需要和RDD中元素类型一致。
seqOp操作会聚合各分区中的元素,然后combOp操作把所有分区的聚合结果再次聚合,两个操作的初始值都是zeroValue. seqOp的操作是遍历分区中的所有元素(T),第一个T跟zeroValue做操作,结果再作为与第二个T做操作的zeroValue,直到遍历完整个分区。combOp操作是把各分区聚合的结果,再聚合。aggregate函数返回一个跟RDD不同类型的值。因此,需要一个操作seqOp来把分区中的元素T合并成一个U,另外一个操作combOp把所有U聚合。
例子程序:
- scala> val rdd = List(1,2,3,4,5,6,7,8,9)
- rdd: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9)
- <span style="color:#330000;">
- scala> rdd.par.aggregate((0,0))(
- (acc,number) => (acc._1 + number, acc._2 + 1),
- (par1,par2) => (par1._1 + par2._1, par1._2 + par2._2)
- )
- res0: (Int, Int) = (45,9)
- scala> res0._1 / res0._2
- res1: Int = 5
- 过程大概这样:
- 首先,初始值是(0,0),这个值在后面2步会用到。
- 然后,(acc,number) => (acc._1 + number, acc._2 + 1),number即是函数定义中的T,这里即是List中的元素。所以acc._1 + number,acc._2 + 1的过程如下。
- 1. 0+1, 0+1
- 2. 1+2, 1+1
- 3. 3+3, 2+1
- 4. 6+4, 3+1
- 5. 10+5, 4+1
- 6. 15+6, 5+1
- 7. 21+7, 6+1
- 8. 28+8, 7+1
- 9. 36+9, 8+1
- </span><strong><span style="color:#ff0000;">结果即是(45,9)</span></strong><span style="color:#330000;">。这里演示的是单线程计算过程,实际Spark执行中是分布式计算,可能会把List分成多个分区,假如3个,p1(1,2,3,4),p2(5,6,7,8),p3(9),经过计算各分区的的结果(10,4),(26,4),(9,1),这样,执行(par1,par2) =>(par1._1 + par2._1, par1._2 + par2._2)就是(10+26+9,4+4+1)即(45,9),再求平均值就简单了。</span>
2. aggregateByKey函数:
对PairRDD中相同的Key值进行聚合操作,在聚合过程中同样使用了一个中立的初始值。和aggregate函数类似,aggregateByKey返回值的类型不需要和RDD中value的类型一致。因为aggregateByKey是对相同Key中的值进行聚合操作,所以aggregateByKey'函数最终返回的类型还是PairRDD,对应的结果是Key和聚合后的值,而aggregate函数直接返回的是非RDD的结果。
例子程序:
- <span style="font-family:'Times New Roman';font-size:18px;">import org.apache.spark.SparkConf
- import org.apache.spark.SparkContext
- object AggregateByKeyOp {
- def main(args:Array[String]){
- val sparkConf: SparkConf = new SparkConf().setAppName("AggregateByKey").setMaster("local")
- val sc: SparkContext = new SparkContext(sparkConf)
- val data=List((1,3),(1,2),(1,4),(2,3))
- val rdd=sc.parallelize(data, 2)
- //合并不同partition中的值,a,b得数据类型为zeroValue的数据类型
- def combOp(a:String,b:String):String={
- println("combOp: "+a+"\t"+b)
- a+b
- }
- //合并在同一个partition中的值,a的数据类型为zeroValue的数据类型,b的数据类型为原value的数据类型
- def seqOp(a:String,b:Int):String={
- println("SeqOp:"+a+"\t"+b)
- a+b
- }
- rdd.foreach(println)
- //zeroValue:中立值,定义返回value的类型,并参与运算
- //seqOp:用来在同一个partition中合并值
- //combOp:用来在不同partiton中合并值
- val aggregateByKeyRDD=rdd.aggregateByKey("100")(seqOp, combOp)
- sc.stop()
- }
- }</span>
运行结果:
将数据拆分成两个分区 //分区一数据
(1,3)
(1,2)
//分区二数据
(1,4)
(2,3) //分区一相同key的数据进行合并
seq: 100 3 //(1,3)开始和中立值进行合并 合并结果为 1003
seq: 1003 2 //(1,2)再次合并 结果为 10032 //分区二相同key的数据进行合并
seq: 100 4 //(1,4) 开始和中立值进行合并 1004
seq: 100 3 //(2,3) 开始和中立值进行合并 1003 将两个分区的结果进行合并
//key为2的,只在一个分区存在,不需要合并 (2,1003)
(2,1003) //key为1的, 在两个分区存在,并且数据类型一致,合并
comb: 10032 1004
(1,100321004)
Spark操作—aggregate、aggregateByKey详解的更多相关文章
- Spark算子篇 --Spark算子之aggregateByKey详解
一.基本介绍 rdd.aggregateByKey(3, seqFunc, combFunc) 其中第一个函数是初始值 3代表每次分完组之后的每个组的初始值. seqFunc代表combine的聚合逻 ...
- Spark算子之aggregateByKey详解
一.基本介绍 rdd.aggregateByKey(3, seqFunc, combFunc) 其中第一个函数是初始值 3代表每次分完组之后的每个组的初始值. seqFunc代表combine的聚合逻 ...
- Spark log4j日志配置详解(转载)
一.spark job日志介绍 spark中提供了log4j的方式记录日志.可以在$SPARK_HOME/conf/下,将 log4j.properties.template 文件copy为 l ...
- IOS数据库操作SQLite3使用详解(转)
iPhone中支持通过sqlite3来访问iPhone本地的数据库.具体使用方法如下1:添加开发包libsqlite3.0.dylib首先是设置项目文件,在项目中添加iPhone版的sqlite3的数 ...
- [Spark内核] 第36课:TaskScheduler内幕天机解密:Spark shell案例运行日志详解、TaskScheduler和SchedulerBackend、FIFO与FAIR、Task运行时本地性算法详解等
本課主題 通过 Spark-shell 窥探程序运行时的状况 TaskScheduler 与 SchedulerBackend 之间的关系 FIFO 与 FAIR 两种调度模式彻底解密 Task 数据 ...
- [转]使用python来操作redis用法详解
转自:使用python来操作redis用法详解 class CommRedisBase(): def __init__(self): REDIS_CONF = {} connection_pool = ...
- C语言对文件的操作函数用法详解2
fopen(打开文件) 相关函数 open,fclose 表头文件 #include<stdio.h> 定义函数 FILE * fopen(const char * path,const ...
- C语言对文件的操作函数用法详解1
在ANSIC中,对文件的操作分为两种方式,即: 流式文件操作 I/O文件操作 一.流式文件操作 这种方式的文件操作有一个重要的结构FILE,FILE在stdio.h中定义如下: typedef str ...
- python操作redis用法详解
python操作redis用法详解 转载地址 1.redis连接 redis提供两个类Redis和StrictRedis用于实现Redis的命令,StrictRedis用于实现大部分官方的命令,并使用 ...
- iBatis——自动生成DAO层接口提供操作函数(详解)
iBatis——自动生成DAO层接口提供操作函数(详解) 在使用iBatis进行持久层管理时,发现在使用DAO层的updateByPrimaryKey.updateByPrimaryKeySelect ...
随机推荐
- 微信开发准备(四)--nat123内网地址公网映射实现
转自:http://www.cuiyongzhi.com/post/37.html 在前面几篇中我们一直说的开发准备工作主要是基于开发框架上的,这里我们说的就逐渐接近开发过程中的实体操作了,如果你之前 ...
- python闭包和装饰器的理解
闭包: 两个函数的嵌套,外部函数返回内部函数的引⽤,外部函数⼀定有参数 def 外部函数(参数): def 内部函数(): pass return 内部函数 他跟函数之间的区别: 1.格式两个函数嵌套 ...
- Tornado抽象方法抽象类
#!/usr/bin/env python #抽象方法抽象类 import abc class Foo(metaclass=abc.ABCMeta): def f1(self): raise Exce ...
- 在zookeeper集群的基础上,搭建solrCloud
1 将在window中部署的单机版solr上传到node-01中 cd /export/software/ rz 选择资料中的solr.zip进行上传(此zip就是 solr的简单部署:在tomca ...
- Zookeeper Api(java)入门与应用
如何使用 Zookeeper 作为一个分布式的服务框架,主要用来解决分布式集群中应用系统的一致性问题,它能提供基于类似于文件系统的目录节点树方式的数据存储,但是 Zookeeper 并不是用来专门存储 ...
- SpringBoot20 集成SpringSecurity02 -> 利用SpringSecurity进行前后端分离的登录验证
1 SpirngBoot环境搭建 创建一个SpringBoot项目即可,详情参见三少的相关博文 参考博文 -> 点击前往 SpirngBoot项目脚手架 -> 点击前往 2 引入Spirn ...
- opennebula 镜像池
{ "IMAGE_POOL": { "IMAGE": [ { ", ", ", "TEMPLATE": { & ...
- 面试题:SSH项目总结 !=!=未看 没用
阿玻罗软件(上海)有限公司已经两年了.中国银行营销系统,到民生银行小微信贷工厂建设.再到交通银行ioffice移动平台项目.以前所学的SSH好多都用不上 公司的框架.都是负责项目的贷款查找模块开发和测 ...
- 2014年:Linux和开源的福祸之年
(1)Heartbleed漏洞 Heartbleed漏洞,是今年开源软件曝出的最大糗事.Heartbleed漏洞是OpenSSL的重大漏洞,这项严重缺陷(CVE-2014-0160)的产生是由于未能在 ...
- Django--form验证及错误处理
需求 from表单验证和ajax验证时返回的错误信息处理 速查 1.form表单提交时错误信息显示 views 1 2 error = form表单实例化对象.errors return render ...