键值对操作

键值对RDD 通常用来进行聚合计算。我们一般要先通过一些初始ETL(抽取、转化、装载)操作来将数据转化为键值对形式。键值对RDD 提供了一些新的操作接口(比如

统计每个产品的评论,将数据中键相同的分为一组,将两个不同的RDD 进行分组合并等)。

1. 创建Pair RDD

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

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

      pari RDD 支持 RDD所支持的函数。例如,我们可以拿前一节中的pair RDD, 筛选掉长度超过20个字符的行。

   result = pairs.filter(lambda keyValue: len(keyValue[1]) < 20)
      如果只想访问RDD的值部分,可以使用mapValues(func)函数

2. 聚合操作

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

    rdd.mapValues(lambda x: (x, 1)).reduceByKey(lambda x, y: (x[0] + y[0], x[1] + y[1]))
     (2) 使用reduceByKey() 对所有的单词进行计数。
   rdd = sc.textFile("s3://...")
   words = rdd.flatMap(lambda x: x.split(" "))
   result = words.map(lambda x: (x, 1)).reduceByKey(lambda x, y: x + y)
      事实上,我们可以对第一个RDD 使用countByValue() 函数,以更快地实现单词计数:input.flatMap(x => x.split(" ")).countByValue()。

     (3) 在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()

          (4)  并行度调优

在执行聚合或分组操作时,可以要求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) # 自定义并行度
         

3  数据分组

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

除了对单个RDD 的数据进行分组,还可以使用一个叫作cogroup() 的函数对多个共享同一个键的RDD 进行分组。对两个键的类型均为K 而值的类型分别为V W RDD 进行cogroup() 时,得到的结果RDD 类型为[(K, (Iterable[V], Iterable[W]))]


4  数据分区


4.1  分区操作

Spark 程序可以通过控制, RDD 分区方式来减少通信开销。

rdd.partitionBy(100).persist()

  

4.2 从分区中获益的操作

数据分区中获益的有cogroup()groupWith()join()leftOuterJoin()rightOuterJoin()groupByKey()reduceByKey()combineByKey() 以及lookup()。对于join()这类二元操作,预先进行数据分区会让其中至少一个RDD不发生数据混洗操作。如果两个RDD 使用同样的分区方式,并且它们还缓存在同样的机器上(比如一个RDD 是通过mapValues() 从另一个RDD 中创建出来的,这两个RDD 就会拥有相同的键和分区方式),或者其中一个RDD 还没有被计算出来,那么跨节点的数据混洗就不会发生了。


4.3 自动分区的操作

这里列出了所有会为生成的结果RDD 设好分区方式的操作:cogroup()groupWith()join()lef tOuterJoin()rightOuterJoin()groupByKey()reduceByKey()combineByKey()partitionBy()sort()mapValues()(如果父RDD 有分区方式的话)、flatMapValues()(如果父RDD 有分区方式的话),以及filter()(如果父RDD 有分区方式的话)。其他所有的操作生成的结果都不会存在特定的分区方式。


4.4 自定义分区

Python 中,不需要扩展Partitioner 类,而是把一个特定的哈希函数作为一个额外的参数传给RDD.partitionBy() 函数,如例4-27 所示。

import urlparse
def hash_domain(url):
return hash(urlparse.urlparse(url).netloc)
rdd.partitionBy(20, hash_domain) # 创建20个分区


























       


   

       

   

    



 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值