Learning Spark - LIGHTNING-FAST DATA ANALYSIS 第三章 - (3)
来源:互联网 发布:淘宝北卡大学是正品吗 编辑:程序博客网 时间:2024/04/30 00:18
更新,第三章完整版PDF可下载:Learning Spark 第三章 RDD编程 已翻译整理完毕,PDF可下载
续啊续,再续上一篇:Learning Spark - LIGHTNING-FAST DATA ANALYSIS 第三章 - (2)
常见的变换和动作
在本章中,我们巡视一遍Spark中最常见的变换和动作。对包含某种类型数据的RDD还有些另外的操作可用,比如RDD的数量的统计函数,对RDD的key/value对按照key进行聚合的key/value操作。在后面的章节中我们会讲到RDD类型之间的转换和其他操作。
基本RDD
我们先从对于不管是什么数据的RDD都适用的变换和动作说起。
元素级的变换
两个最常见的你可能用到的变换是map()和filter()(见图3-2)。map()变换传入一个函数,并将该函数应用到RDD中的每一个元素。函数的返回结果就是变换后的每个元素构成的新RDD。filter()变换也是传入一个函数,返回的是该RDD中仅能通过该函数的元素构成的新RDD。
图 3-2 从输入RDD中map和filter后的RDD
我们可以用map()做任何的事情,从我们的集合中取出网站关联的每个url到计算平方数。map()的返回类型不必和输入类型相同,这很有用。如果我们有一个String类型的RDD,通过map()将字符串解析后返回double,那么我们的输入类型就是RDD[String],而结果类型就是RDD[Double]。
让我们看一个map()的简单例子,计算RDD中所有数的平方(示例3-36到3-28)。
示例3-26:Python计算RDD中的平方值
nums = sc.parallelize([1, 2, 3, 4])
squared = nums.map(lambda x: x * x).collect()
for num in squared:
print "%i " % (num)
示例3-27:Scala计算RDD中的平方值
val input = sc.parallelize(List(1, 2, 3, 4))
val result = input.map(x => x * x)
println(result.collect().mkString(","))
示例3-28:Java计算RDD中的平方值
JavaRDD<Integer> rdd = sc.parallelize(Arrays.asList(1, 2, 3, 4));
JavaRDD<Integer> result = rdd.map(new Function<Integer, Integer>() {
public Integer call(Integer x) { return x*x; }
});
System.out.println(StringUtils.join(result.collect(), ","));
有时我们想为每个输入元素产生多个输出元素。这个操作叫做flatMap()。和map()一样,我们提供给flatMap()的函数被输入RDD中的每个元素单独调用,但不是返回单个元素,而是返回的一个返回值的迭代器。与其说是产生了一个迭代器的RDD,不如说是得到了一个来自所有迭代器的元素组成的RDD。flatMap()的一个简单用法是分割输入字符串到单词,见示例3-29到3-31。
示例3-29 Python中使用flatMap()分割文本行到单词
lines = sc.parallelize(["hello world", "hi"])
words = lines.flatMap(lambda line: line.split(" "))
words.first() # returns "hello"
示例3-30 Scala中使用flatMap()分割文本行到单词
val lines = sc.parallelize(List("hello world", "hi"))
val words = lines.flatMap(line => line.split(" "))
words.first() // returns "hello"
示例3-31 Java中使用flatMap()分割文本行到单词
JavaRDD<String> lines = sc.parallelize(Arrays.asList("hello world", "hi"));
JavaRDD<String> words = lines.flatMap(new FlatMapFunction<String, String>() {
public Iterable<String> call(String line) {
return Arrays.asList(line.split(" "));
}
});
words.first(); // returns "hello"
在图3-3中我们说明了flatMap()和map()之间的不同。你可以认为flatMap()是“压扁”了返回给它的迭代器。所以最终得到的不是一个list的RDD,而是这些list中的元素的RDD。
图 3-3 flatMap()和map()之间的区别
伪集合操作
RDD支持许多数学集合操作,比如并集合交集。甚至即使RDD本身不是严格的集合。图3-4列出了4个操作。这里的重点是所有这些操作要求被操作的RDD是同一个类型。
图 3-4 一些简单的集合操作
我们的RDD中最常丢失的集合属性是唯一性,经常会有重复元素。如果需要元素唯一可以用RDD.distinct()变换来生成一个新的无重复元素的RDD。然而,请注意distinct()很昂贵,因为它需要所有的数据通过网络进行Shuffling以确保唯一性。我们将在第四章详细讨论关于Shuffling以及如何避免它。
最简单的集合运算是union(other),它返回一个由两个源的数据一起组成的RDD。在有些情况下会有用,比如处理来自多个源的日志文件。和数学意义上的并集不同,如果在输入的多个RDD中有重复元素,则Spark的union()的结果也有重复元素(可以通过dictinct()修复)。
Spark也提供了intersection(other)方法,它返回两个RDD中都存在的元素。Intersection()也会去除所有的重复元素(包括在单个RDD中存在的重复元素)。虽然union()和intersection()是相似的概念,但是intersection()的性能要差得多。因为它需要通过网络shuffle数据来识别公共元素。
有时我们需要根据想法去掉一些数据。subtract(other)函数传入一个RDD,返回的是只在第一个RDD中存在并且不在第二个RDD中存在的值的RDD。就像intersection()一样,也需要shuffle数据。
我们还可以计算两个RDD的笛卡尔积,如图3-5。cartesian(other)变换返回(a,b)的所有可能的组合,其中a在源RDD中,b在另一个RDD中。笛卡儿积在我们考虑所有可能的组合的相似性的时候会有用,比如计算用户对每个机会感兴趣的预期。也可以对RDD自己做笛卡儿积,对于用户相似度类似的任务会有用。然而请注意,笛卡儿积操作对于太大的RDD来说非常昂贵。
图 3-5 计算两个RDD的笛卡儿积
表3-2和3-3汇总了常见的RDD变换。
表格 3-2 对一个包含{1, 2, 3, 3}的RDD进行基本的变换
函数名
目的
示例
结果
map()
应用函数到RDD中的每个元素,并返回一个结果RDD
rdd.map(
x => x + 1 )
{2, 3, 4, 4}
flatMap()
应用函数到RDD中的每个元素,并返回一个返回的迭代器内容的RDD,通常用于提取单词
rdd.flatMap(
x => x.to(3) )
{1, 2, 3, 2, 3, 3, 3}
filter()
返回由仅通过传入filter()的条件的元素组成的RDD
rdd.filter(
x => x != 1 )
{2, 3, 3}
distinct()
去重
rdd.distinct()
{1, 2, 3}
Sample(withReplacement, fraction, [seed])
RDD采样数据,可替换
rdd.sample(
false, 0.5)
Nondeterministic
表格 3-3 对包含{1, 2, 3}和{3, 4, 5}的两个RDD进行变换
函数名
目的
示例
结果
union()
生成一个包含两个RDD中所有元素的RDD
rdd.union(other )
{1, 2, 3, 3, 4, 5}
intersection()
生成两个RDD中都有的元素组成的RDD
rdd.intersection(other)
{3}
subtract()
从一个RDD中去掉另一个RDD中存在的元素(比如去掉训练数据)
rdd.subtract(other)
{1, 2}
cartesian()
生成两个RDD的笛卡尔积的RDD
rdd.cartesian(other)
{(1, 3), (1, 4), ..., (3,5)}
- Learning Spark - LIGHTNING-FAST DATA ANALYSIS 第三章 - (3)
- Learning Spark - LIGHTNING-FAST DATA ANALYSIS 第三章 - (1)
- Learning Spark - LIGHTNING-FAST DATA ANALYSIS 第三章 - (2)
- Learning Spark - LIGHTNING-FAST DATA ANALYSIS 第三章 - (4)
- Learning Spark - LIGHTNING-FAST DATA ANALYSIS 第四章 - (3)
- Learning Spark - LIGHTNING-FAST DATA ANALYSIS 第四章 - (1)
- Learning Spark - LIGHTNING-FAST DATA ANALYSIS 第四章 - (2)
- Learning Spark - LIGHTNING-FAST DATA ANALYSIS 第四章 - (4)
- Learning Spark: Lightning-Fast Big Data Analysis 中文翻译
- Learning Spark: lightning-fast big data analysis (1)
- Learning Spark: lightning-fast big data analysis (2)
- Spark是什么?(翻译自Learning.Spark.Lightning-Fast.Big.Data.Analysis)
- Spark Core and Cluster Managers(翻译自Learning.Spark.Lightning-Fast.Big.Data.Analysis)
- Spark核心概念介绍(翻译自Learning.Spark.Lightning-Fast.Big.Data.Analysis)
- 单独的应用程序(翻译自Learning.Spark.Lightning-Fast.Big.Data.Analysis)
- Spark的Python和Scala shell介绍(翻译自Learning.Spark.Lightning-Fast.Big.Data.Analysis)
- 友情序言 to 《Learning Spark: Lightning-fast big data analytics》
- 友情序言 to 《Learning Spark: Lightning-fast big data analytics》
- JAVA语言基础知识总结
- 学习感悟
- 清晰认识JavaScript函数
- Android事件处理第一节(View对Touch事件的处理)
- 使用mysql 中间件 Atlas 实现数据库读写分离
- Learning Spark - LIGHTNING-FAST DATA ANALYSIS 第三章 - (3)
- IOS 9 关于微信,QQ三方登陆的https适配结局方案,XCODE配置
- 【思想感悟】——如何激发自己的正能量
- 基于struts框架的文件上传
- JAVA_SE基础——32.this关键字调用本类的构造方法
- Works Applications2016校园招聘 — Game
- 八分钟诠释什么是万向节死锁(Gimbal Lock)
- Python 安装boto boto3
- 开始自己的技术博客生涯