(4)键值对操作

4.1动机

键值对RDD是Spark中许多操作所需要的常见数据类型。键值对RDD通常用来进行聚合计算。我们一般要先通过一些初始ETL操作来讲数据转化为键值对形式。

Spark为包含键值对类型的RDD提供了一些专有的操作,这些RDD被称为pair RDD,pair RDD是很多程序的构成要素,因为他们提供了并行操作各个键或跨节点重新进行数据分组的操作接口。

4.2创建Pair RDD

Spark有很多创建pair RDD的方式,很多存储键值对的数据格式会在读取时直接返回由键值对数据组成的pair RDD。

此外,当需要把一个普通RDD转换为pair RDD时,可以调用map函数来实现,传递的函数需要返回键值对。

例如:在Python中使用第一个单词作为键创建出一个pair RDD

pairs = lines.map(lambda x: (x.split("")[0], x))

4.3Pair RDD的转化操作

Pair RDD可以使用所有标准RDD上的可用的转化操作

reduceByKey(func)                 #合并具有相同键的值
groupByKey                        #对具有相同键的值进行分组
combineBy                         #使用不同的返回类型合并具有相同键的值
mapValues               #对pair RDD中的每一个值应用一个函数而不改变键值
keys                  #返回一个仅包含键的RDD
values #返回一个仅包含值的RDD
sortByKey               #返回一个根据键排序的RDD
subtractByKey #删掉RDD中键与other RDD中的键相同的元素
join #对两个RDD进行内连接
cogroup #将两个RDD钟拥有相同键的数据分组到一起
rightOuterJoin #对两个RDD进行连接操作,确保第一个RDD的键必须存在
leftOuterJoin
#对两个RDD进行连接操作,确保第一个RDD的键必须存在

用Python对第二个元素进行筛选

result = pairs.filter(lambda keyValue: len(keyValue[1]) < 20)

 4.3.1聚合操作

reduceByKey会为数据集中的每个键进行并行的归约操作,每个归约操作会将键相同的值合并起来。

在Python中使用reduceByKey和mapValues计算每个键对应的平均值

rdd.mapValues(lambda x: (x,1)).reduceByKey(lambda x,y: (x[0]+y[0], x[1]+y[1]))

 


combineByKey是最为常用的基于键进行聚合的函数。,他可以让用户返回与输入数据的类型不同的返回值。

在Python中使用combineByKey求每个键对应的平均值

sumCount = nums.combineByKey((lambda x:(x,1),(lambda x,y: (x[0]+y, x[1]+1)),(lambda x,y:(x[0]+y[0],x[1]+y[1])))
sumCount.map(lambda key, xy:(key,xy[0]/xy[1])).collectAsMap()

 每个RD都有固定数目的分区,分区数决定了在RDD上执行操作时的并行度。在执行聚合或分组操作时,可以要求Spark使用给定的分区数,Spark会始终尝试根据集群的大小腿短出一个有意义的默认值。

在Python中兹定于reduceByKey的并行度

data = [("a",3),("b",4),("a",1)]
sc.parallelize(data).reduceByKey(lambda x,y:x+y)      #默认并行度
sc.parallelize(data).reduceByKey(lambda x,y:x+y,10) #自定义并行度

如果我们希望在除分组操作和聚合操作之外的操作中也能改变RDD的分区,Spark提供了repartition函数,它会把数据通过网络进行混洗,并创建出新的分区集合,但是这是一种代价相对比较大的操作。有一个优化版本的函数,叫做ccoalesce,在Python中,rdd.getNumPartitions可以查看RDD的分区数,并确保调用coalesce时将RDD合并到比现在的分区更少的分区中。

4.3.2数据分组

如果数据已经以预期的方式提取了键,groupByKey就会使用RDD中的键来对数据进行分组。对于一个由类型K的键和类型V的值组成的RDD,所得到的结果RDD类型会是[K, Iterable[V]]。

这个函数也可以用于未成对的数据上,也可以根据除键意外的条件进行分组。它可以接收一个函数,对源RDD中的每个元素使用该函数,将返回结果作为键再进行分组。

除了对单个RDD的键进行分组,还可以使用一个叫做cogroup的函数对多个共享同一个键的RDD进行分组。

4.3.3连接

将有键的数据与另一组有键的数据一起使用是对键值对数据执行的最有用的操作之一。

普通的join操作符表示内连接。

4.3.4数据排序

在Python中以字符串顺序对整数进行自定义排序

rdd.sortByKey(ascending=True, numPartitions=None, keyfunc=lambad x: str(x))

4.4Pair RDD的行动操作

countByKey                           #对每个键对应的元素分别计数
collectAsMap                         #将结果一映射表的形式返回,以便查询
lookup(key)                          #返回给定键对应的所有值

 

posted @ 2017-01-24 10:44  cyoutetsu  阅读(1222)  评论(0编辑  收藏  举报