transformation转换算子详细案例大全

本文详述了Spark中的各种转换操作,包括map、mapPartitions、flatMap、filter、sample、union、join、coalesce/repartition等。通过实例解析了每个算子的功能和使用场景,如数据抽样、数据融合、键值对操作等,帮助理解Spark数据处理的核心概念。
摘要由CSDN通过智能技术生成

map

rdd.map(func):RDD,对rdd集合中的每一个元素,都作用一次该func函数,之后返回值为生成元素构成的一个新的RDD。

   listRDD.map(num => num * 7)

mapPartitions/mapPartitionsWithIndex

/**
   * map(p: A => B)
   *     对集合中的每一条记录操作,将元素A转化为元素B
   * mapPartitions(p: Iterator[A] => Iterator[B])
   *    上面的map操作,一次处理一条记录;而mapPartitions一次性处理一个partition分区中的数据
   * 注意:
   *     虽说mapPartitions的执行性能要高于map,但是其一次性将一个分区的数据加载到执行内存空间,如果该分区数据集比较大,存在OOM的风险
   * mapPartitionsWithIndex((index, p: Iterator[A] => Iterator[B]))
   *     该操作比mapPartitions多了一个index,代表就是后面p所对应的分区编号
   *
   *     rdd的分区编号,命名规范,如果又N个分区,分区编号就从0,。。,N-1
   */
  //mapPartitions
  def mapPartitionsFunction(sc:SparkContext): Unit ={
   
    val arr=1 to 10
    val rdd:RDD[Int] = sc.parallelize(arr)
    var a=rdd.mapPartitions(partition=>{
   
      val list = partition.toList
      println(list.mkString(","))
      list.map(_*2).toIterator//本来只执行这里就行,但因为我想打印一下,而迭代器遍历一次就失效了,所以转成list
    })
    a.foreach(println)
  }
  //mapPartitionsWithIndex
  def mapPartitionsWithIndexFunction(sc:SparkContext): Unit ={
   
    val arr=1 to 10
    val rdd:RDD[Int] = sc.parallelize(arr)
    rdd.mapPartitionsWithIndex((index,partition)=>{
   
      val list = partition.toList
      println(s"分区${index}的数据为:${list.mkString(",")}")
      list.map(_*2).toIterator
    }).count()
  }

flatMap

rdd.flatMap(func):RDD ==>rdd集合中的每一个元素,都要作用func函数,返回0到多个新的元素,这些新的元素共同构成一个新的RDD。所以和上述map算子进行总结:

map操作是一个one-2-one的操作

flatMap操作是一个one-2-many的操作

filter

rdd.filter(func):RDD ==> 对rdd中的每一个元素操作func函数,该函数的返回值为Boolean类型,保留返回值为true的元素,共同构成一个新的RDD,过滤掉哪些返回值为false的元素。

sc.parallelize(list) .filter(_ % 2 == 0)

sample

sample(withReplacement, fraction, seed):随机抽样算子
sample主要工作就是为了来研究数据本身,去代替全量研究会出现类似数据倾斜(dataSkew)等问题,无法进行全量研究,只能用样本去评估整体。

首先得要知道这三个参数是啥意思

withReplacement:抽样的方式,true有放回抽样, false为无返回抽样

fraction: 抽样比例,取值范围就是0~1

seed: 抽样的随机数种子,有默认值,通常也不需要传值

案例:从10w个数中抽取千分之一进行样本评估

def sampleMapOps(sc:SparkContext): Unit = {
   
    val listRDD = sc.parallelize(1 to 100000)

    var sampledRDD = listRDD.sample(true, 0.001)
    println("样本空间的元素个数:" + sampledRDD.count())
    sampledRDD = listRDD.sample(false, 0.001)
    println("样本空间的元素个数:" + sampledRDD.count())
}

union

/**
   * rdd1.union(rdd2)
   *  相当于sql中的union all,进行两个rdd数据间的联合,需要说明一点是,该union是一个窄依赖操作,
   *  rdd1如果又N个分区,rdd2又M个分区,那么union之后的分区个数就为N+M
   */
  def unionfun(sc:SparkContext): Unit ={
   
    //给两个rdd,每个rdd设置两个分区测试,结果union后 应该有四个分区
    val value = sc.parallelize(1 to 10,2)
    value.mapPartitionsWithIndex((index,partition)=>{
   
      val list = partition.toList
      println(s"分区${index}-->${list.mkString(",")}")
      list.toIterator
    }).count()
    println("----------1-----------")
    val value1 = sc.parallelize(20 to 30,2)
    value.mapPartitionsWithIndex((index,partition)=>{
   
      val list = partition.toList
      println(s"分区${index}-->${list.mkString(",")}")
      list.toIterator
    }).count()
    println("---------2---------")
    val value2 = value.union(value1)
    value2.mapPartitionsWithIndex((index,partition)=>{
   
      val list = partition.toList
      println(s"分区${index}-->${list.mkString(",")}")
      list.toIterator
    }).count()//写上action算子,触发执行
  }

join

sparkcore中支持的连接有:笛卡尔积、内连接join,外连接(左、右、全)

要想两个RDD进行连接,那么这两个rdd的数据格式,必须是k-v键值对的,其中的k就是关联的条件,也就是sql中的on连接条件。

//join,leftOuterJoin,rightOuterJoin
  def join(sc:SparkContext): Unit ={
   
    
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值