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的数量的统计函数,对RDDkey/value对按照key进行聚合的key/value操作。在后面的章节中我们会讲到RDD类型之间的转换和其他操作。

基本RDD

我们先从对于不管是什么数据的RDD都适用的变换和动作说起。

 

元素级的变换

两个最常见的你可能用到的变换是map()filter()(见图3-2)。map()变换传入一个函数,并将该函数应用到RDD中的每一个元素。函数的返回结果就是变换后的每个元素构成的新RDDfilter()变换也是传入一个函数,返回的是该RDD中仅能通过该函数的元素构成的新RDD

 

图 3-2 从输入RDDmapfilter后的RDD

 

我们可以用map()做任何的事情,从我们的集合中取出网站关联的每个url到计算平方数。map()的返回类型不必和输入类型相同,这很有用。如果我们有一个String类型的RDD,通过map()将字符串解析后返回double,那么我们的输入类型就是RDD[String],而结果类型就是RDD[Double]

 

让我们看一个map()的简单例子,计算RDD中所有数的平方(示例3-363-28)。

 

示例3-26Python计算RDD中的平方值
nums = sc.parallelize([1, 2, 3, 4])
squared = nums.map(lambda x: x * x).collect()
for num in squared:
    print "%i " % (num)

示例3-27Scala计算RDD中的平方值
val input = sc.parallelize(List(1, 2, 3, 4))
val result = input.map(x => x * x)
println(result.collect().mkString(","))


示例3-28Java计算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,不如说是得到了一个来自所有迭代器的元素组成的RDDflatMap()的一个简单用法是分割输入字符串到单词,见示例3-293-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()是“压扁”了返回给它的迭代器。所以最终得到的不是一个listRDD,而是这些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中有重复元素,则Sparkunion()的结果也有重复元素(可以通过dictinct()修复)。

 

Spark也提供了intersection(other)方法,它返回两个RDD中都存在的元素。Intersection()也会去除所有的重复元素(包括在单个RDD中存在的重复元素)。虽然union()intersection()是相似的概念,但是intersection()的性能要差得多。因为它需要通过网络shuffle数据来识别公共元素。

 

有时我们需要根据想法去掉一些数据。subtract(other)函数传入一个RDD,返回的是只在第一个RDD中存在并且不在第二个RDD中存在的值的RDD。就像intersection()一样,也需要shuffle数据。

 

我们还可以计算两个RDD的笛卡尔积,如图3-5cartesian(other)变换返回(a,b)的所有可能的组合,其中a在源RDD中,b在另一个RDD中。笛卡儿积在我们考虑所有可能的组合的相似性的时候会有用,比如计算用户对每个机会感兴趣的预期。也可以对RDD自己做笛卡儿积,对于用户相似度类似的任务会有用。然而请注意,笛卡儿积操作对于太大的RDD来说非常昂贵。

 

图 3-5 计算两个RDD的笛卡儿积

3-23-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)}

 


0 0
原创粉丝点击