在Spark中有许多聚类操作是基于combineByKey的,例如group那个家族的操作等。所以combineByKey这个函数也是比较重要,所以下午花了点时间看来下这个函数。也参考了http://www.tuicool.com/articles/miueaqv这篇博客。

先看下combineByKey定义:
/**
   * Generic function to combine the elements for each key using a custom set of aggregation
   * functions. Turns an RDD[(K, V)] into a result of type RDD[(K, C)], for a "combined type" C
   * Note that V and C can be different -- for example, one might group an RDD of type
   * (Int, Int) into an RDD of type (Int, Seq[Int]). Users provide three functions:
   *
   * - `createCombiner`, which turns a V into a C (e.g., creates a one-element list)
   * - `mergeValue`, to merge a V into a C (e.g., adds it to the end of a list)
   * - `mergeCombiners`, to combine two C's into a single one.
   *
   * In addition, users can control the partitioning of the output RDD, and whether to perform
   * map-side aggregation (if a mapper can produce multiple items with the same key).
   */
  def combineByKey[C](createCombiner: V => C,
    mergeValue: (C, V) => C,
    mergeCombiners: (C, C) => C,
    partitioner: Partitioner,
    mapSideCombine: Boolean = true,
    serializer: Serializer = null): RDD[(K, C)] = {
  //实现略
  }
这个函数主要是将键值对[(K,V)]转换为[(K,C)],并且这里的V,C类型可以不同。
对于里面的三个函数的作用,上述的博客的例子讲得很通俗,所以就拿过来直接讲下。
假设我们要将一堆的各类水果给榨果汁,并且要求果汁只能是纯的,不能有其他品种的水果。那么我们需要一下几步:
1 定义我们需要什么样的果汁
2 定义一个榨果汁机,即给定水果,就能给出我们定义的果汁
3 定义一个果汁混合器,即能将相同类型的水果果汁给混合起来。
那么有了这三步,我们就只需要往这个果汁机中仍水果,那么这个果汁机就会产生果汁,并且果汁经过果汁混合器就能将相同品种的水果给聚在一块了。
那么对比上述三步,combineByKey的三个函数也就是这三个功能
1 createCombiner就是定义了v如何转换为c
2 mergeValue 就是定义了如何给定一个V将其与原来的C合并成新的C
3 就是定义了如何将相同key下的C给合并成一个C
下面以一个例子来说明,例如有
data=sc.parallelize([("a",2),("a",3),("b",4)])这个数据,后面的数字表示该字符权重,我们现在想求每个字符出现的平均权重。
data.combineByKey((lambda v:(v,1)),
                              (lambda c,v:(c[0]+v,c[1]+1)),
                              (lambda x,y:(x[0]+y[0],x[1]+y[1])))
那么第一个函数
第二个函数
(lambda c,v:(c[0]+v,c[1]+1)) 这里的参数c可以理解为已经榨好的果汁,v为新加进去的水果,在这里假设此时c为(2,1)v为3,那么应该对应的权重相加,并且计数加1,c[0]+v就是权重相加,c[0]是2,接着就是对其计数加1.(其实这里已经是对相同的key进行归类了,否则c和v的key不同,在这里就会混乱)
第三个函数
(lambda x,y:(x[0]+y[0],x[1]+y[1])),这里是将相同品种的水果果汁给混合起来,所以这里的参数x,y其实都是c类型的。所以这里需要做的就是相应的的权重相加,并且计数相加。这里的x[0]+y[0]就是权重相加,x[1]+y[1]就是计数相加。
 
利用combineByKey实现groupByKey
groupByKey是将key相同的value聚合成一个list
data=sc.parallelize([("a",2),("a",3),("b",4),("b",2)])
一开始自己的写法是:

temp=data.combineByKey((lambda v:[v]),
            (lambda c,v:c.append(v)),
            (lambda x,y:x.extend(y)))

但总是返回[("a",None),("b",None)]后来才发现原来是因为python中对于list.append()没有返回值,所以c.append(v)返回值为None。但是这三个函数都是需要返回值的。对于第二个而言返回的是V加入C后的C,对于第三个而言返回的是C和另一个C合并后的C

所以

def g(c,v);

  c.append(v)

  return c

def h(c1,c2):

  c1.extend(c2)

  return c1

data.combineByKey((lambda v:[v]),g,h)这样就能正确返回了

 
总结:
虽然对于细节了解不够深,但是猜测第二个函数像是Hadoop中的local combiner就是对本地中的相同的key的水果进行榨汁混合,第三个函数像是在全局中对相同的key的水果进行混合(此时不需要榨汁了)。
 
 
 

Spark 的combineByKey函数的更多相关文章

  1. Spark入门(六)--Spark的combineByKey、sortBykey

    spark的combineByKey combineByKey的特点 combineByKey的强大之处,在于提供了三个函数操作来操作一个函数.第一个函数,是对元数据处理,从而获得一个键值对.第二个函 ...

  2. 自定义实现spark的分区函数

    有时自己的业务需要自己实现spark的分区函数 以下代码是实现一个自定义spark分区的demo 实现的功能是根据key值的最后一位数字,写到不同的文件 例如: 10写入到part-00000 11写 ...

  3. Spark远程调试函数

    Spark远程调试函数 1.sendInfo 该函数用于分布式程序的调试,非常方便,在spark的rdd操作中嵌入sendInfo,启动nc服务器后,可以收集到所有需要的运行时信息,该函数可以捕获ho ...

  4. Spark SQL 自定义函数类型

    Spark SQL 自定义函数类型 一.spark读取数据 二.自定义函数结构 三.附上长长的各种pom 一.spark读取数据 前段时间一直在研究GeoMesa下的Spark JTS,Spark J ...

  5. spark中的combineByKey函数的用法

    一.函数的源码 /** * Simplified version of combineByKeyWithClassTag that hash-partitions the resulting RDD ...

  6. Spark核心RDD:combineByKey函数详解

    https://blog.csdn.net/jiangpeng59/article/details/52538254 为什么单独讲解combineByKey? 因为combineByKey是Spark ...

  7. Spark RDD——combineByKey

    为什么单独讲解combineByKey? 因为combineByKey是Spark中一个比较核心的高级函数,其他一些高阶键值对函数底层都是用它实现的.诸如 groupByKey,reduceByKey ...

  8. spark之combineByKey

    combineByKey def combineByKey[C](createCombiner: (V) => C, mergeValue: (C, V) => C, mergeCombi ...

  9. Spark SQL 用户自定义函数UDF、用户自定义聚合函数UDAF 教程(Java踩坑教学版)

    在Spark中,也支持Hive中的自定义函数.自定义函数大致可以分为三种: UDF(User-Defined-Function),即最基本的自定义函数,类似to_char,to_date等 UDAF( ...

随机推荐

  1. js、html中的单引号、双引号及其转义使用

    js.html中的单引号.双引号及其转义使用在js中对相关字符做判断或取值的时候很多情况下都会用到这些. ------ 在一个网页中的按钮,写onclick事件的处理代码,不小心写成如下:<in ...

  2. Hibernate 系列教程11-继承-Single Table策略

    Single Table策略 通过 discriminator鉴别器来区分是父类还是子类 Employee public class Employee { private Long id; priva ...

  3. UITableView的子控件高度不确定处理

    比如,tableView的tableFootView的控件数量是根据网络请求的数据而定的.那么tableView并不能准确的设置其contentSize.处理方法: 在tableFootView的类中 ...

  4. UICollectionView 浅析

    什么是UICollectionView UICollectionView是一种新的数据展示方式,简单来说可以把他理解成多列的UITableView(请一定注意这是UICollectionView的最最 ...

  5. 在win7/8/10鼠标右键添加“管理员取得所有权”

    Windows Registry Editor Version 5.00 [HKEY_CLASSES_ROOT\*\Shell\TakeAuthority]"icon"=" ...

  6. ab测试 uwsgi遇到的问题

    1 请求并发数目较大时,接收到的数目小于发送的数目 1.1 描述:uwsgi正常返回302跳转 ab -n 5000 -c 250 -g test.log "192.168.50.20:90 ...

  7. Cisco 绑定mac地址

    在Cisco中有以下三种方案可供选择,方案1和方案2实现的功能是一样的,即在具体的交换机端口上绑定特定的主机的MAC地址(网卡硬件地址),方案3是在具体的交换机端口上同时绑定特定的主机的MAC地址(网 ...

  8. Android SERVICE后台服务进程的自启动和保持

    Service组件在android开发中经常遇到,其经常作为后台服务,需要始终保持运行,负责处理一些必要(见不得人)的任务.而一些安全软件,如360等,会有结束进程的功能,如果不做Service的保持 ...

  9. emacs redo

    c / c/ cg c/ cg c/ tramp: /sudo::/usr/

  10. js选择一个选项 跳出另一个选项 跳出一个输入框

    跳出输入框 <script language="javascript"> function $(obj){return document.getElementById( ...