Spark 常用高级算子--记录

aggregate聚合,是一个action

有一个初始值,有两个函数参数,第一个是把各个分区聚合,第二个分区结果聚合
例如


   val rdd1 = sc.parallelize(List(1,2,3,4,5,6,7,8,9), 2)
   rdd1.aggregate(0)(_+_, _+_)  //先对第一个分区数求和,在对各个分区后的数据求和
   rdd1.aggregate(10)(_+_, _+_)//10与各个个分区数值相加,最后各个分区结果值再与初始值10相加
                               //结果为10+1+2+3+4+10+5+6+7+8+9+10
   
   rdd1.aggregate(5)(math.max(_, _), _ + _)//math.max(_, _) 将每个分区数据取出进行两两比较取最大,分区结果相加
                                               //初始值为5,将初始值5与每个分区数据进行比较,第一个分区值为5,第二个为9,
                                               //再与初始值相加结果为5+5+9=19
                                           

定义一个函数查看各个分区数据分布


   val func1= (index: Int, iter:Iterator[(Int)]) => {
       iter.toList.map(x => "[partID:" +  index + ", val: " + x + "]").iterator}
   val rdd1 = sc.parallelize(List(1,2,3,4,5,6,7,8,9), 2)
   rdd1.mapPartitionsWithIndex(func1).collect

分区数据结果
在这里插入图片描述

   val rdd4 = sc.parallelize(List("12","23","345",""),2)
   rdd4.aggregate("")((x,y) => math.min(x.length, y.length).toString, (x,y) => x + y)
    
    //空字符串math为0
    //先 math.min("".length,"12".length)    res int=0   toString 为"0"
   //math.min("0".length,"23".length)
   //math.min("345".lengtg,"".length)      res int =0

aggregateByKey

对key分组进行操作,先进行局部操作,在进行整理操作

   val pairRDD = sc.parallelize(List( ("cat",2), ("cat", 5), ("mouse", 4),("cat", 12), ("dog", 12), ("mouse", 2)), 2)
   def func2(index: Int, iter: Iterator[(String, Int)]) : Iterator[String] = {
     iter.toList.map(x => "[partID:" +  index + ", val: " + x + "]").iterator
           }  //第一个参数分区编号,第二个是迭代器:分区数据,返回一个迭代器
   pairRDD.mapPartitionsWithIndex(func2).collect   

分区数据结果
在这里插入图片描述


  pairRDD.aggregateByKey(0)(math.max(_, _), _ + _).collect
  //把一个区每个key最大值取出,在将每个相同key相加

结果为:
在这里插入图片描述

  pairRDD.aggregateByKey(0)( _ + _, _ + _).collect
  //将每个分区key的值相加,最后再全局统计  将每个key值相加
  pairRDD.reduceByKey()(_ + _).collect  //与aggregateByKey结果相同,
                                      //相当于把_ + _先传给局部函数再传给全局函数

结果为:
在这里插入图片描述

reduceByKey与groupBykey区别

reduce 是先进行局部求和然后进行汇总,reduceByKey底层用的是conbineByKey()(这个底层接口使用必须要写类型)
group将k,v数据都放入一个大集合里面, shuffle的时候会消耗更多的带宽。

combineByKey : 和reduceByKey是相同的效果

分组后,第一个参数:第一个元素取出来进行操作, 第二个参数:是函数, 局部运算, 第三个:是函数, 对局部运算后的结果再做运算
每个分区中每个key中value中的第一个值, (hello,1)(hello,1)(good,1)–>(hello(1,1),good(1))–>x就相当于hello的第一个1, good中的1

  // 从HDFS中读数据,有几个块就会默认分几个区
val rdd1 = sc.textFile("hdfs:/192.168.146.100:9000/wordcount/input/").flatMap(_.split(" ")).map((_, 1))
val rdd2 = rdd1.combineByKey(x => x, (a: Int, b: Int)   => a + b, (m: Int, n: Int) => m + n)  
//x => x, (a: Int, b: Int)   => a + b, 解释
//x => x  将第一个元素原封不动的取出来
//第二个函数必须要写类型,把vlue值原封不动取出来,
//a,b都是局部1,然后相加 

combineByKey 之后为(hello,(1,1,1,1,1))
x相当于一个初始值10+1,局部操作 11+1+1+1+1
在这里插入图片描述


val rdd4 = sc.parallelize(List("dog","cat","gnu","salmon","rabbit","turkey","wolf","bear","bee"), 3)
val rdd5 = sc.parallelize(List(1,1,2,2,2,1,2,2,2), 3)
val rdd6 = rdd5.zip(rdd4)  //拉链操
val rdd7 = rdd6.combineByKey(List(_), (x: List[String], y: String) => x :+ y, (m: List[String], n: List[String]) => m ++ n)
       
       //val list=List(1)   不可变list 不能直接用+=
       //list:+2            res:List(1,2)   原list没有变还是list=List(1)
       //list++list          res2:List(1,1)  俩list相加
       //list ::: res   res1:List[int]=List(1,1,2)   :+追加一个元素,::: 追加两个list

rdd6 拉链操作结果为:
在这里插入图片描述
rdd7解释:
combineByKey得到(1,(dog,cat,turkey))
第一个函数List(_) 弄一个集合把dog放进去,_就代表将dog放入
第二个函数 将局部追加到List里面。因为第一个将它转为List了 故第一个参数x:List[string] ,第二个参数是其他的字符所以是String。 将字符逐步追加到List里面
第三个函数 将List相加
在这里插入图片描述
结果:在这里插入图片描述

repartition 能对数据重新分区

coalesce, repartition 功能差不多

   val rdd1 = sc.parallelize(1 to 10, 2)  
   val rdd2=rdd1.repartition(3)    //数据可能被打散,进行shuffle 网络传输,跑到另外一台机器上
   val rdd3 = rdd1.coalesce(4)  //第二个参数默认不进行shuffle  结果还是为3个分区
   val rdd3 = rdd1.coalesce(4true) //分区为4个
   rdd3.partitions.length

collectAsMap

把结果放入一个Map

   val rdd = sc.parallelize(List(("a", 1), ("b", 2)))
   rdd.collectAsMap

在这里插入图片描述

countByKey

计算Key的数量

   val rdd1 = sc.parallelize(List(("a", 1), ("b", 2), ("b", 2), ("c", 2), ("c", 1)))
   rdd1.countByKey

在这里插入图片描述

countByValue

   rdd1.countByValue

在这里插入图片描述

filterByRange

返回一个范围

   val rdd1 = sc.parallelize(List(("e", 5), ("c", 3), ("d", 4), ("c", 2), ("a", 1)))
   val rdd2 = rdd1.filterByRange("b", "d")
   rdd2.collect

在这里插入图片描述

flatMapValues

先把value处理

   val rdd3 = sc.parallelize(List(("a", "1 2"), ("b", "3 4")))
   val rdd4 = rdd3.flatMapValues(_.split(" "))
   rdd4.collect
   //  Array((a,1), (a,2), (b,3), (b,4))

foldByKey

   val rdd1 = sc.parallelize(List("dog", "wolf", "cat", "bear"), 2)
   val rdd2 = rdd1.map(x => (x.length, x))   //将字母长度与字母放入一个元组里
   val rdd3 = rdd2.foldByKey("")(_+_)        //将相同key的value拼接
   //结果res14: Array[(Int, String)] = Array((4,wolfbear), (3,dogcat))

foreach

对每一个rdd元素进行操作

foreachPartition

把每一个分区进行操作,不会产生一个新的rdd

keyBy 以传入的参数做key

val rdd1 = sc.parallelize(List("dog", "salmon", "salmon", "rat", "elephant"), 3)
val rdd2 = rdd1.keyBy(_.length)  //把长度作为key   
val rdd3 = rdd1.keyBy(_(0))     //第一个字母作为key  
rdd2.collect
//结果rdd2: Array[(Int, String)] = Array((3,dog), (6,salmon), (6,salmon), (3,rat), (8,elephant))

keys values

    val rdd1 = sc.parallelize(List("dog", "tiger", "lion", "cat", "panther", "eagle"), 2)
    val rdd2 = rdd1.map(x => (x.length, x))
    rdd2.keys.collect    //把key取出来 res18: Array[Int] = Array(3, 5, 4, 3, 7, 5)
    rdd2.values.collect //把value取出来 res19: Array[String] = Array(dog, tiger, lion, cat, panther, eagle)

http://homepage.cs.latrobe.edu.au/zhe/ZhenHeSparkRDDAPIExamples.html
RDD算子权威解释

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Spark算子Spark框架中的一种操作符,用于对RDD(弹性分布式数据集)进行转换和操作。Scala版本的Spark算子可以通过编写Scala代码来实现,常用算子包括map、filter、reduce、join等。这些算子可以帮助开发者快速地进行数据处理和分析,提高数据处理效率和准确性。 ### 回答2: Spark算子Spark中的一个很重要的概念,它主要是用于数据的转换和处理。在Scala版本中,Spark算子有两种不同的类型,一个是转换操作的算子,另一个是行动操作的算子。这些算子被组织成RDD的API,以便在分布式环境中进行操作,从而实现高效的计算。 对于Spark算子来说,它的灵活性和方便性是非常重要的。因为在实际应用中,数据的处理往往是非常复杂和混杂的。这时,使用Spark算子可以很快地将数据转换成需要的格式,以便进行后续的处理。同时,Spark算子还可以极大地提高处理数据的效率,因为它们是在分布式集群上进行处理的,这样就可以大大缩短处理时间。 在Scala版本中,首要的算子是map算子,它可以非常方便地对数据进行转换。除此之外,还有很多常用算子,比如flatMap、reduceByKey、groupBy等,它们都具有一些独特的特性和用法,可以根据实际情况选择使用。当然,对于更加复杂的数据处理操作,也可以自定义函数来实现。Spark算子可以很容易地与自定义函数进行结合,从而实现更加灵活的数据处理操作。 总之,Spark算子Spark中一个非常重要的概念,它可以帮助我们高效地转换和处理数据。在Scala版本中,Spark算子是非常方便和易用的,可以满足各种不同场景下的需求。无论是初学者还是专业人士,都可以通过学习Spark算子来进一步提高自己的数据处理和计算能力。 ### 回答3: Spark是一种流行的分布式计算框架,它提供了自己的编程模型,称为Resilient Distributed Datasets(RDDs)。Scala是一种运行在Java虚拟机上的编程语言,它可以与Spark很好地配合使用,为Spark提供了Scala API,使得开发者可以使用Scala语言进行Spark开发。 在Scala API中,Spark提供了很多有用的算子,这些算子可以用于在分布式集群上操作RDDs。这些算子可以分为两类:转换算子和动作算子。 转换算子用于接受一个RDD,并返回一个新的RDD,这个新的RDD表示对原始RDD的一些转换操作。在这里,我们可以使用各种不同的转换功能,例如map、flatMap和filter。这些算子允许我们执行各种数据操作,例如将一组元素映射到另一组元素,或者仅选择符合某些条件的元素,等等。 动作算子用于接受一个RDD,并返回单个结果。这些算子在执行过程中会计算原始RDD的结果,并将结果返回给驱动程序。这些算子包括reduce、count、collect和foreach等。在这里,我们可以使用这些算子计算和收集RDD中特定的元素或结果。 总之,Spark算子Spark Scala API中的核心组件,使得开发者可以简便地操作分布式计算集群上的大型数据集。这些算子是开发Spark应用程序的基本部分,开发者应该了解它们的工作方式,以便能够更高效地处理数据。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值