PySpark之Spark中的CombineByKey

九、Spark中的CombineByKey

combineByKey是Spark中一个比较核心的高级且底层函数,其他一些高阶键值对函数底层都是用它实现的。诸如 groupByKey,reduceByKey等等

如下解释下3个重要的函数参数:

  • createCombiner: V => C ,这个函数把当前的值作为参数,此时我们可以对其做些附加操作(类型转换)并把它返回 (这一步类似于初始化操作)
  • mergeValue: (C, V) => C,该函数把元素V合并到之前的元素C(createCombiner)上 (这个操作在每个分区内进行)
  • mergeCombiners: (C, C) => C,该函数把2个元素C合并 (这个操作在不同分区间进行)。

案例一:实现将相同Key的Value进行合并,使用groupBy很容易实现

# -*- coding: utf-8 -*-
# Program function:外部集合转为RDD

from pyspark import SparkConf, SparkContext
import re

# 1-准备环境
conf = SparkConf().setAppName("collection").setMaster("local[*]")
sc = SparkContext(conf=conf)
sc.setLogLevel("WARN")

x = sc.parallelize([("a", 1), ("b", 1), ("a", 2)])
def to_list(a):
    return [a]

def append(a, b):
    a.append(b)
    return a

def extend(a, b):
    a.extend(b)
    return a


print(sorted(x.combineByKey(to_list, append, extend).collect()))
#[('a', [1, 2]), ('b', [1])]
  • 作用
    • 对数据集按照 Key 进行聚合
  • 调用
    • combineByKey(createCombiner, mergeValue, mergeCombiners, [partitioner], [mapSideCombiner], [serializer])
  • 参数
    • createCombiner 将 Value 进行初步转换
    • mergeValue 在每个分区把上一步转换的结果聚合
    • mergeCombiners 在所有分区上把每个分区的聚合结果聚合
    • partitioner 可选, 分区函数
    • mapSideCombiner 可选, 是否在 Map 端 Combine
    • serializer 序列化器
  • 注意点
    • combineByKey 的要点就是三个函数的意义要理解
    • groupByKey, reduceByKey 的底层都是 combineByKey

案例二:求平均分的案例代码

# -*- coding: utf-8 -*-
# Program function:外部集合转为RDD

from pyspark import SparkConf, SparkContext
import re

# 1-准备环境
conf = SparkConf().setAppName("collection").setMaster("local[*]")
sc = SparkContext(conf=conf)
sc.setLogLevel("WARN")

x = sc.parallelize([("Fred", 88), ("Fred", 95), ("Fred", 91), ("Wilma", 93), ("Wilma", 95), ("Wilma", 98)])


# (v)=>(v,1),得到的是(88,1),因为这是combineByKey是按照key处理value操作,
# acc:(Int,Int)代表的是(88,1),其中acc._1代表的是88,acc._2代表1值,v代表是同为Fred名称的95的数值,
# 所以acc._1+v=88+95,即相同Key的Value相加结果,第三个参数是分区间的相同key的value进行累加,
# 得到Fred的88+95+91,Wilma累加和为93+95+98。
def createCombiner(a):
    return [a, 1]
def mergeValue(a, b):
    return [a[0] + b, a[1] + 1]
def mergeCombiners(a, b):
    return [a[0] + b[0], a[1] + b[1]]
resultKey = x.combineByKey(createCombiner, mergeValue, mergeCombiners)
print(sorted(resultKey.collect()))
# [('Fred', [274, 3]), ('Wilma', [286, 3])]
print(resultKey.map(lambda score: (score[0], int(score[1][0]) / int(score[1][1]))).collect())
# [('Fred', 91.33333333333333), ('Wilma', 95.33333333333333)]
#lambda表达式版本
resultKey = x.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]])
print(sorted(resultKey.collect()))
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值