一些操作对所有类型的RDD都可以使用,而另一些操作只能在特殊的RDD类型使用。例如只有对于元素都是数字的RDD才能计算平均值。在下面的操作都是在RDD上通用的操作。
Transformations
map()
Map函数和MapReduce中的map意义相同,即返回一个新RDD,其元素是输入RDD中元素,按照某个规则得到的新元素。输入输出的RDD中包含的元素是一一对应的。
例如下例中,将nums中的每个元素自乘。
nums = sc.parallelize([1, 2, 3, 4])
squared = nums.map(lambda x: x * x)flatmap()
有时需要让RDD中的一个元素产生多个对应元素。如下例:
lines = sc.parallelize([“hello world”, “hi”])
words = lines.flatMap(lambda line: line.split(” “))filter()
返回一个新RDD,其元素是输入RDD元素中符合过滤条件的那些元素。union()
返回一个包含两个输入RDD元素的新RDD。intersection()
返回一个新RDD,其元素是两个输入RDD元素的交集。subtract()
返回一个新RDD,其元素是第一个输入RDD的元素且不是第二个输入RDD的元素。sample()
返回一个新RDD,其元素是输入RDD元素中符合按规则sample出来的那些元素。
Actions
reduce()
Reduce函数和MapReduce中的Reduce意义相同,用于对RDD中的数据做聚合操作。例如:
rdd = sc.parallelize([1,2,3,4,5])
rdd.reduce(lambda a,b:a+b)
其中输入参数为两个,输出1个。a代表聚合结果,b代表RDD中的元素。a+b则表示a=a+b,即将RDD中的所有元素累加到a上,且a为聚合的结果,15.count()
返回RDD元素的个数。collect()
有多种方式可以将RDD中的所有元素返回driver program,collect()是常用的一个。大家知道一个RDD的多个分区通常分布在集群中的各个节点内存里,而collect()将这些分散的RDD分区数据全部传回driver program所在的机器,合并后返回给driver program。
因此如果数据集很大,可能超过driver program所在机器的内存时,不建议使用collect()。take(n)
返回指定个数的RDD元素,返回的元素是随机的。top()
默认安装RDD中元素的顺序返回一个元素,也可以使用比较函数来返回最大或最小的元素。aggregate()
和reduce类似,但可以返回不同类型的RDD。
另有一类常用的RDD,称为Pair RDD。Pair RDD的元素是一个key value pair组成的元组:
sc.parallelize([(“a”, 3), (“b”, 4), (“a”, 1)])
这里“a”为key,1为value。
Pair RDD很常用,因为我们经常需要按照key对数据做聚合操作。这类RDD操作操作起来略有不同。例如下例,需要对key和value分别处理:
input=sc.parallelize([“1 test string”,”2 test a long string”])
pair = input.map(lambda x: (x.split(” “)[0], x))
result = pair.filter(lambda x: len(x[1]) < 15)
result.collect()
另外reduce的用法也有变化:
from operator import add
rdd = sc.parallelize([(“a”, 1), (“b”, 1), (“a”, 1)])
sorted(rdd.reduceByKey(add).collect())
返回结果:[(‘a’, 2), (‘b’, 1)]
上例需要注意的是,由于调用redueceByKey会导致Spark在各个分区上分别计算当前分区的聚合值,因此redueceByKey不会将结果返回给driver program,在它之后可调用collect()将结果汇总后返回给driver program。