pyspark_聚合操作

一、聚合方法

大型数据集中,为了减少shuffle的数据量,相对于groupByKey来说,使用reduceByKey、combineByKey以及foldByKey 会是更好的选择

  • 数据
def create_pair(t3):
    return (t3[0], int(t3[2]))

def create_pair_sumcnt(t3):
    name = t3[0]
    number = int(t3[2])
    return (name, (number, 1))

spark = SparkSession.builder.appName('avg_by_key').getOrCreate()
list_of_tuples = [('alex', 'Sunnyvale', 25),
                  ('alex', 'Sunnyvale', 33),
                  ('alex', 'Sunnyvale', 45),
                  ('alex', 'Sunnyvale', 63),
                  ('mary', 'Ames', 22),
                  ('mary', 'Cupertino', 66),
                  ('mary', 'Ames', 20),
                  ('bob', 'Ames', 26)]
rdd = spark.sparkContext.parallelize(list_of_tuples)
rdd_pair = rdd.map(lambda t: create_pair(t))

rdd_pair1 = rdd.map(lambda x: create_pair_sumcnt(x))

1.1 aggregateByKey

  1. 预设初始值 zero_tuple = (0, 0)
  2. Comb操作,每个数值变量变化 例如 2 -> (2, 1)
  3. Reduce 操作
sum_count = rdd_pair.aggregateByKey(
    (0 , 0),
    lambda zero_tuple, values_: (zero_tuple[0] + values_, zero_tuple[1] + 1),
    lambda tup0, tup1: (tup0[0] + tup1[0], tup0[1]+tup1[1])  # reduce
)

1.2 acombineByKey

  • 源码
def combineByKey[C](
  createCombiner: V => C,
  mergeValue: (C, V) => C,
  mergeCombiners: (C, C) => C): RDD[(K, C)] = self.withScope {
combineByKeyWithClassTag(createCombiner, mergeValue, mergeCombiners)(null)
}

1、createCombiner:V=>C  分组内的创建组合的函数。通俗点将就是对读进来的数据进行初始化,其把当前的值作为参数,可以对该值做一些转换操作,转换为我们想要的数据格式

2、mergeValue:(C,V)=>C  该函数主要是分区内的合并函数,作用在每一个分区内部。其功能主要是将V合并到之前(createCombiner)的元素C上 ,注意,这里的C指的是上一函数转换之后的数据格式,而这里的V指的是原始数据(上一函数为转换之前的)

3、mergeCombiners:(C,C)=>R  该函数主要是进行多分取合并,此时是将两个C合并为一个C,例如两个C:(Int)进行相加之后得到一个R:(Int)。相当于reduce(底层调用相同)。

combineByKey与reduceByKey的区别是:combineByKey可以返回与输入数据类型不一样的输出。

  • 例子
sum_count1 = rdd_pair.combineByKey(
    lambda values_: (values_, 1), # createCombiner
    lambda combined, values_: (combined[0] + values_, combined[1] + 1), # 在combined中叠加
    lambda values_, cnts: (values_[0] + cnts[0], values_[1]+cnts[1])  # reduce
)

1.3 foldByKey

sum_count2 = rdd_pair1.foldByKey(
    (0, 0),  # zero_value = (0, 0) = (sum, count)
    lambda x, y : (x[0] + y[0], x[1] + y[1])
)

1.4 groupby

sum_count3 = rdd_pair.groupByKey().mapValues(lambda x : (sum(list(x)), len(list(x))))
# 或者分步减少计算
#  sum_count3 = rdd_pair.groupByKey().mapValues(lambda x : list(x) )
#  avg = sum_count3.map(lambda x : float(sum(x)) / float(len(x)))

1.5 reduceByKey

sum_count4 = rdd_pair1.reduceByKey(
    lambda fs, nd: (fs[0] + nd[1], fs[0] + nd[1])
    )

参考: https://github.com/mahmoudparsian/pyspark-algorithms

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Scc_hy

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

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

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

打赏作者

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

抵扣说明:

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

余额充值