RDD的键值对操作(pair RDD)

RDD的键值对操作

创建

  • 可以从RDD中直接通过map函数进行创建

    lines = sc.textFile("file:///usr/local/spark/README.md")
    pairs = lines.map( lambda x : (x.split(" ")[0], x) ) # 将第一行的第一个单词作为key,该行字符串作为value,构建pairRDD
    print( pairs.count() )
    print( pairs.first() )
    

基本操作

  • filter:对pair RDD的元素按照某种规则进行过滤,去掉不需要的pair RDD
  • reduceByKey:对pairRDD中的元素中所有相同key对应的元素进行统计,下面是单词个数统计的例子

    lines = sc.textFile("file:///usr/local/spark/README.md")
    words = lines.flatMap( lambda x : x.split(" ") )
    result = words.map( lambda x : (x,1) ).reduceByKey(lambda x,y:x+y) # 统计所有单词出现的次数
    print( result.collect() )
    
  • combineByKey:这是pair RDD中一个非常核心的操作,groupByKey、reduceByKey都是由combineByKey实现的,它有三个参数

    • combine function:可以将RDD[K,V]中的V转化为一个新的值C1
    • 分区内的merge function:合并值函数,将一个C1类型值和一个V类型值合并为一个C2类型,输入参数为(C1,V),输出为(C2),这是在分区内进行的
    • 分区之间的merge function:将两个C2整合为1个C3类型的值,输入(C2,C2),输出为C3

      x = sc.parallelize([('B',1),('B',2),('A',3),('A',4),('A',5)])
      createCombiner = (lambda el : (el, el**2))
      
      mergeVal = (lambda aggregated, el : aggregated + (el, el**2))
      mergeComb = (lambda agg1, agg2 : agg1+agg2)
      
      y = x.combineByKey( createCombiner, mergeVal, mergeComb )
      print( x.collect() )
      print( y.collect() )
      
  • 设置分区个数:每个RDD都有固定数目的分区,在建立RDD时,如果不指定分区个数的话,系统会根据集群大小推断出一个有意义的默认值。

    # 并行度调优
    data = [("a",3), ("b",4), ("c",5), ("a", 6)]
    ret1 = sc.parallelize(data).reduceByKey( lambda x,y:x+y )
    ret2 = sc.parallelize(data).reduceByKey( lambda x,y:x+y, 10 )
    print( ret1.collect() )
    print( ret2.collect() )
    

数据分组

  • groupBy:对RDD对象中的元素进行分组,返回一个list,list中的每个元素都是一个key与满足该组分组条件的元素列表
  • groupByKey:对pair RDD中相同key对应的元素进行合并,形成一个元素列表作为value,key值保持不变

    data = [("a",3), ("b",4), ("c",5), ("a", 6)]
    rdd = sc.parallelize( data )
    ret1 = rdd.groupByKey().mapValues(len).collect() # 统计相同key的个数
    ret2 = rdd.groupByKey().mapValues(list).collect() # 将相同key对应的value进行合并
    print(ret1)
    print(ret2)
    

数据连接

  • join:对于2个pair RDD中都含有的key,设其value为v1,v2,返回一个pair RDD,其中的元素为(key, (v1,v2))

    x = sc.parallelize([("a", 1), ("b", 4)])
    y = sc.parallelize([("a", 2), ("a", 3), ("b", 5)])
    ret = x.join(y).collect()
    print(ret)
    
  • leftOuterJoin与rightOuterJoin:允许key值有缺失的连接,分别允许右边与左边的值有缺失,对应为None

    x = sc.parallelize([("a", 1), ("c", 4)])
    y = sc.parallelize([("a", 2), ("b", 5)])
    ret = x.leftOuterJoin(y).collect()
    print(ret)
    
    x = sc.parallelize([("a", 1), ("c", 4)])
    y = sc.parallelize([("a", 2), ("b", 5)])
    ret = x.rightOuterJoin(y).collect()
    print(ret)
    

数据排序

  • sortByKey:按照key进行升序或者降序排列,可以指定比较key时采用的函数,即不是比较key1与key2,而是比较f(key1)与f(key2),但是f(key)的返回值类型需要与key相同。

    x = sc.parallelize([(2, 2), (1, 3), (3, 5), (13, 4)])
    ret = x.sortByKey( ascending=True, numPartitions=None, keyfunc=lambda x: -x ) # 原本设置的升序排列,这里将key变成相反数,相当于降序排列
    print( ret.collect() )
    

pair RDD的行动操作

  • countByKey:对每个key对应的元素个数进行计数
  • collectAsMap:将结果以映射表的形式返回,便于查询
  • lookup:返回给定键对应的所有值,为list的形式

    x = sc.parallelize([(2, 2), (1, 3), (3, 5), (13, 4), (2,233)])
    print( x.countByKey() )
    print( x.collectAsMap() ) # 对于相同key值,只保留一个value
    print( x.lookup(2) )
    

关于数据分区的进一步说明

  • 在实际处理中,如果涉及到定时将采集到的数据放入本机上的数据集中,在不对本机数据集进行正确分区的情况下,在join的时候可能性能会很差,但是如果将本机数据集转化为许多个哈希分区,每个hash分区都有唯一的hash值,那么在加入新的数据时,效率会高很多。
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

littletomatodonkey

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值