Spark学习摘记 —— RDD行动操作API归纳
本文参考
参考《Spark快速大数据分析》动物书中的第三章"RDD编程",前一篇文章已经概述了转化操作相关的API,本文再介绍行动操作API
和转化操作API不同的是,行动操作API只能作用于一个RDD
RDD转化操作API归纳:https://www.cnblogs.com/kuluo/p/12545374.html
Pair RDD转化操作API归纳:https://www.cnblogs.com/kuluo/p/12558563.html
Pair RDD行动操作API归纳:https://www.cnblogs.com/kuluo/p/12567221.html
环境
idea + spark 2.4.5 + scala 2.11.12
RDD均通过SparkContext的parallelize()函数创建
collect()函数
目的:
返回RDD中的所有元素
代码:
val testList = List(1, 2, 3, 3)
val testRdd = sc.parallelize(testList)
testRdd.collect().foreach(ele => print(s"$ele "))
输出:
1 2 3 3
注意:
该函数会将所有元素放入驱动器进程中,只有当整个数据集能在单台机器的内存中放得下时,才能使用,不适宜用在大规模数据集,因此大多数情况下用于本地开发测试,以下还会碰到很多这样不适合大数据量访问的函数
count()函数
目的:
返回RDD中的元素个数
代码:
val testList = List(1, 2, 3, 3)
val testRdd = sc.parallelize(testList)
println(testRdd.count())
输出:
4
countByValue()函数
目的:
各元素在RDD中出现的次数
在经典的WordCount示例程序中我们一般先通过flatMap()函数进行压扁,再用map()函数转为pair RDD,最后用reduceByKey()函数进行计数,实际上我们可以通过countByValue()函数,将WordCount示例程序中的map()函数和reduceByKey()函数两步操作,合并为一步
代码:
val testList = List(1, 2, 3, 3)
val testRdd = sc.parallelize(testList)
testRdd.countByValue().foreach(ele => print(s"$ele "))
输出:
(1,1) (3,2) (2,1)
和WordCount程序的对比:
val testList = List("a a a a b b c c", "a a c c c d d", "b b c c d", "a b c d")
val testRdd = sc.parallelize(testList)
testRdd.flatMap(line =>
line.split(" ")
).map(ele =>
(ele, 1)
).reduceByKey{case (x, y) =>
x + y
}.foreach(pair => print(s"$pair "))
使用countByValue后
val testList = List("a a a a b b c c", "a a c c c d d", "b b c c d", "a b c d")
val testRdd = sc.parallelize(testList)
testRdd.flatMap(line =>
line.split(" ")
).countByValue().foreach(pair => print(s"$pair "))
两个示例程序输出结果相同:(d,4) (a,7) (b,5) (c,8)
注意:
尽管使用该函数能够简化我们的编程,但是在源码中有如下注释:
This method should only be used if the resulting map is expected to be small, as the whole thing is loaded into the driver's memory.
To handle very large results, consider using rdd.map(x => (x, 1L)).reduceByKey(_ + _) , which returns an RDD[T, Long] instead of a map.
由此可见countByValue()函数也会将所有元素加载到驱动器进程,建议在数据集不大的情况下使用
另外一点要注意的是,countByValue()函数返回的RDD中的每个元素的类型是Map,但并不是我们常说的pair RDD,pair RDD相关的转化和行动操作不能应用在元素类型是Map的RDD上
take()函数
目的:
从RDD中返回num个元素,将尽可能访问少的分区
代码:
val testList = List(3, 4, 2, 1, 9, 6, 3, 6, 8, 9)
val testRdd = sc.parallelize(testList)
testRdd.take(5).foreach(pair => print(s"$pair "))
输出:
3 4 2 1 9(不一定)
注意:
This method should only be used if the resulting array is expected to be small, as all the data is loaded into the driver's memory.
take ()函数也会将所有元素加载到驱动器进程,建议在返回元素不多的情况下使用
takeSample()函数
目的:
从RDD中返回任意一些元素
代码:
val testList = List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
val testRdd = sc.parallelize(testList)
testRdd.takeSample(true, 5).foreach(pair => print(s"$pair "))
输出:
0 4 0 3 2(会出现重复元素)
代码:
val testList = List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
val testRdd = sc.parallelize(testList)
testRdd. takeSample(false, 5).foreach(pair => print(s"$pair "))
输出:
0 3 8 2 7(不会出现重复元素)
sample()函数、take()函数和takeSample()函数的区别:
sample()函数是转化操作API,withReplacement参数取false时,fraction参数取[0, 1]并表示RDD中每个元素被选中的可能性
take()函数是行动操作API,从RDD中抽取由num参数指定的数量的元素,首先访问RDD中的第一个分区,若第一个分区中的元素个数已经能够满足我们num参数指定的数量,将不再访问其它分区,即尽可能少地访问RDD分区,以下为take()函数源码注释
Take the first num elements of the RDD. It works by first scanning one partition, and use the results from that partition to estimate the number of additional partitions needed to satisfy the limit.
takeSample()函数是行动操作API,从withReplacement参数取false时,结果RDD中不会出现重复元素,num参数表示要取得的元素的个数
sample()函数和takeSample()函数都有第三个参数seed用来设置随机数种子,保证每次抽取RDD元素的结果集不同
take()函数和takeSample()函数被明确指明各元素会被加载到驱动器进程,不适合大数据量的情况下使用
top()函数
目的:
从RDD中返回最前面的num个元素,降序排序
内部实际上调用takeOrdered()函数
代码:
val testList = List(3, 4, 2, 1, 9, 6, 3, 6, 8, 9)
val testRdd = sc.parallelize(testList)
testRdd.top(5).foreach(pair => print(s"$pair "))
等价写法
val testList = List(3, 4, 2, 1, 9, 6, 3, 6, 8, 9)
val testRdd = sc.parallelize(testList)
testRdd.takeOrdered(5)(Ordering[Int].reverse).foreach(pair => print(s"$pair "))
输出:
9 9 8 6 6
takeOrdered()函数
目的:
从RDD中按照提供的顺序返回最前面的num个元素,默认升序排序
代码:
val testList = List(3, 4, 2, 1, 9, 6, 3, 6, 8, 9)
val testRdd = sc.parallelize(testList)
testRdd.takeOrdered(5).foreach(pair => print(s"$pair "))
输出:
1 2 3 3 4
reduce()函数
目的:
并行整合RDD中所有数据,操作两个相同元素类型的RDD数据返回一个同样类型的新元素
代码:
val testList = List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
val testRdd = sc.parallelize(testList)
println(testRdd.reduce(_ + _))
输出:
45
fold()函数
目的:
和reduce()函数一样,但需要提供初始值,提供的初始值应当是你提供的操作的单位元素,如加法运算的单位元素是0,乘法运算的单位元素是1
代码:
val testList = List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
val testRdd = sc.parallelize(testList)
println(testRdd.fold(0)(_ + _))
输出:
45
aggregate()函数
目的:
和reduce()函数相似,但返回值类型可以和操作的RDD类型不同,需要提供初始值,合并RDD内元素的函数以及将不同节点上的元素进行合并
代码:
val testList = List(3, 4, 5, 3, 8, 6, 6, 7, 9, 1)
val testRdd = sc.parallelize(testList)
val result:(Int, Int)
= testRdd.aggregate((0, 0))((x, y)
=> {
(x._1 + y, x._2 + 1)
}, (x, y) => {
(x._1 + y._1, x._2 + y._2)
})
print(1.0 * result._1 / result._2)
计算平均值,在本例中aggregate()函数返回的是一个Tuple元组
输出:
5.2
foreach()函数
目的:
对RDD中的每个元素使用给定的函数,在前面的示例中均以出现,此处不再做演示
更高效的操作:
val testList = List(3, 4, 5, 3, 8, 6, 6, 7, 9, 1)
val testRdd = sc.parallelize(testList)
testRdd.foreachPartition(partition => {
partition.foreach(ele => {
print(s"$ele ")
})
})
输出:3 4 5 3 8 6 6 7 9 1
Spark学习摘记 —— RDD行动操作API归纳的更多相关文章
- Spark学习摘记 —— RDD转化操作API归纳
本文参考 在阅读了<Spark快速大数据分析>动物书后,大概了解到了spark常用的api,不过书中并没有给予所有api具体的示例,而且现在spark的最新版本已经上升到了2.4.5,动物 ...
- Spark学习摘记 —— Pair RDD行动操作API归纳
本文参考 参考<Spark快速大数据分析>动物书中的第四章"键值对操作",本篇是对RDD转化操作和行动操作API归纳的最后一篇 RDD转化操作API归纳:https:/ ...
- Spark学习摘记 —— Pair RDD转化操作API归纳
本文参考 参考<Spark快速大数据分析>动物书中的第四章"键值对操作",由于pair RDD的一些特殊操作,没有和前面两篇的API归纳放在一起做示例 前面的几个api ...
- Spark学习之RDD编程(2)
Spark学习之RDD编程(2) 1. Spark中的RDD是一个不可变的分布式对象集合. 2. 在Spark中数据的操作不外乎创建RDD.转化已有的RDD以及调用RDD操作进行求值. 3. 创建RD ...
- spark学习(10)-RDD的介绍和常用算子
RDD(弹性分布式数据集,里面并不存储真正要计算的数据,你对RDD的操作,他会在Driver端转换成Task,下发到Executor计算分散在多台集群上的数据) RDD是一个代理,你对代理进行操作,他 ...
- Spark学习之RDD
RDD概述 什么是RDD RDD(Resilient Distributed Dataset)叫做弹性分布式数据集,是Spark中最基本的数据抽象,它代表一个不可变.可分区.里面的元素可并行计算的集合 ...
- Spark学习之RDD的理解
转自:http://www.infoq.com/cn/articles/spark-core-rdd/ 感谢张逸老师的无私分享 RDD,全称为Resilient Distributed Dataset ...
- Spark学习之RDD编程总结
Spark 对数据的核心抽象——弹性分布式数据集(Resilient Distributed Dataset,简称 RDD).RDD 其实就是分布式的元素集合.在 Spark 中,对数据的所有操作不外 ...
- Spark学习笔记——RDD编程
1.RDD——弹性分布式数据集(Resilient Distributed Dataset) RDD是一个分布式的元素集合,在Spark中,对数据的操作就是创建RDD.转换已有的RDD和调用RDD操作 ...
随机推荐
- 【C# 集合】HashTable .net core 中的Hashtable的实现原理
上一篇我介绍了Hash函数 这篇我来说一下Hash函数在 HashTable中的应用. HashTable的特性: 1.装载因子:.net core 0.72 ,java 0.75 2.冲突解决方案: ...
- C#爬虫(04):HtmlAgilityPack解析html文档
原文链接 https://www.cnblogs.com/springsnow/p/13278283.html 目录 一.爬虫概述 1.使用浏览器获取页面源码 2.HTML解析组件 二.HtmlAgi ...
- MongoDB数据库的下载安装及配置方法
MongoDB安装与配置步骤 MongoDB数据库之安装篇 # 1 下载MongoDB数据库 1.打开浏览器,登录"https://www.mongodb.com/try/download/ ...
- Python——条件语句及其循环
条件语句及其循环 一. 条件语句 在条件语句中可以使用以下所有的运算符: 算术运算符:+.-.*././/.%.** 关系运算符:>.<.==.<=.>=.!= 测试运算符:i ...
- jmeter 24个常用函数
Jmeter_24个常用函数 JMeter提供了很多函数,如果能够熟练使用,可以为脚本带来很多方便. JMeter函数是一种特殊值,可用于除测试计划外的任何组件. 函数调用的格式如下所示:${__ ...
- Node.js躬行记(16)——活动配置化
一直想将一些常规活动抽象化,制作成可配置的.原先的计划是做成拖拽的,那种可视化搭建,运营也能自己搭建页面. 这是一个美好的愿景,但是现实不允许我花太多精力去制作这样一个系统.经过权衡后,先设计成一个可 ...
- 为什么不让用join?《死磕MySQL系列 十六》
大家好,我是咔咔 不期速成,日拱一卒 在平时开发工作中join的使用频率是非常高的,很多SQL优化博文也让把子查询改为join从而提升性能,但部分公司的DBA又不让用,那么使用join到底有什么问题呢 ...
- Lua中如何实现类似gdb的断点调试—08支持通过包名称添加断点
在前一篇中我们支持了通过函数名称来添加断点,我们同时也提到了在Lua中一个函数的名称的并不是确定的.准确的说,Lua中的函数并没有名称,所谓名称其实是保存这个函数值的变量的名称. 于是通过函数名称添加 ...
- 『现学现忘』Docker基础 — 22、使用Docker安装Nginx
目录 步骤1:搜索镜像 步骤2:下载Nginx镜像 步骤3:运行Nginx镜像 步骤4:进行本机测试 步骤5:进入容器内操作 步骤6:测试外网访问容器 步骤1:搜索镜像 使用docker search ...
- 拉格朗日插值法--python
数据插补 常见插补方法 插值法--拉格朗日插值法 根据数学知识可知,对于平面上已知的n个点(无两点在一条直线上可以找到n-1次多项式 ,使次多项式曲线过这n个点. 1)求已知过n个点的n-1次多项式: ...