大数据组件-sparkTransformations算子,Action算子,速查表

速查表

  • 键值对数据类型支持算子
类别算子
聚合操作reduceByKey;foldByKey;combineByKey
分组操作cogroup,groupByKey
连接操作join;leftOuterJoin;rightOuterJoin
排序操作sortBy;sortByKey
ActioncountByKey;take;collect
  • 数字型数据支持算子
算子含义
count个数
mean均值
sum求和
max最大值
min最小值
variance方差
sampleVariance从采样中计算方差
stdev标准差
sampleStdev采样的标准差

Transformations算子(惰性的)

map

map是针对分区内的每一条数据进行处理rdd.map(item=>(对item做一条数据处理逻辑))

mapPartitions(List[T]->List[U])

1.使用场景

和map类似,但是针对整个分区的数据转换,map的粒度是条数,而mapPartitions粒度是分区数

  1. map的func参数是单条数据,mapPartitions的func参数是一个集合(一个分区整个所有的数据)
  2. map的func返回值也是单条数据,mapPartition的func返回值是一个集合

2.示例

import org.apache.spark.{SparkConf, SparkContext}
import org.junit.Test

class TransformationOp {
  private val conf: SparkConf = new SparkConf().setMaster("local").setAppName("")
  private val sc = new SparkContext(conf)

  @Test
  def mapParttitions: Unit ={
    //1.数据生成
    val rdd = sc.parallelize(List(1,2,3,4,5,6),2)
    //2.算子使用
      .mapPartitions(iter=>{
      iter.foreach(item => println(item))
      iter
    })
    .collect()
    .foreach(item=>println(item))
  }

mapPartitionsWithIndex

1.使用场景

和mapPartitions类似,只是在函数中增加了分区的Index

2.示例

import org.apache.spark.{SparkConf, SparkContext}
import org.junit.Test

class TransformationOp {
  private val conf: SparkConf = new SparkConf().setMaster("local").setAppName("")
  private val sc = new SparkContext(conf)

  
  @Test
  def mapPartitionsWitIndex: Unit ={
    val rdd = sc.parallelize(List(1,2,3,4,5,6),2)
      .mapPartitionsWithIndex((index,iter)=>{
        println("index:"+index)
        iter.foreach(item=>println(item))
        iter
      })
      .collect()
  }
}

mapValues

1.使用场景

MapValues 只能作用于 Key-Value 型数据, 和 Map 类似, 也是使用函数按照转换数据, 不同点是 MapValues 只转换 Key-Value 中的 Value

2.示例

sc.parallelize(Seq(("a", 1), ("b", 2), ("c", 3)))
  .mapValues( value => value * 10 )
  .collect()

在这里插入图片描述

Filter过滤

1.使用场景

Filter 算子的主要作用是过滤掉不需要的内容

2.示例

sc.parallelize(Seq(1, 2, 3))
  .filter( value => value >= 2 )//只要大于2的数据
  .collect()

在这里插入图片描述

sample抽样

1.使用场景

  • Sample 算子可以从一个数据集中抽样出来一部分, 常用作于减小数据集以保证运行速度, 并且尽可能少规律的损失
  • sample(withReplacement, fraction, seed)
  • Sample 接受第一个参数为withReplacement为true表示有放回,false表示无放回
  • Sample 接受第二个参数为fraction, 抽样比例
  • Sample 接受第三个参数为seed, 随机数种子

2.示例

sc.parallelize(Seq(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
  .sample(withReplacement = true, 0.6, 2)
  .collect()

在这里插入图片描述

集合操作-并集union

val rdd1 = sc.parallelize(Seq(1, 2, 3))
val rdd2 = sc.parallelize(Seq(4, 5, 6))
rdd1.union(rdd2)
  .collect()

在这里插入图片描述

集合操作-交集intersection

val rdd1 = sc.parallelize(Seq(1, 2, 3, 4, 5))
val rdd2 = sc.parallelize(Seq(4, 5, 6, 7, 8))
rdd1.intersection(rdd2)
  .collect()

在这里插入图片描述

集合操作-插集subtract

1.使用场景

rdd1里面有的rdd2里面没有的

2.示例

val rdd1 = sc.parallelize(Seq(1, 2, 3, 4, 5))
val rdd2 = sc.parallelize(Seq(4, 5, 6, 7, 8))
rdd1.subtract(rdd2)
  .collect()

reduceByKey

1.使用场景

  • 聚合操作:ReduceByKey 只能作用于 Key-Value 型数据,所有先按照 Key 分组生成一个 Tuple, 然后针对每个组执行 reduce 算子
  • def reduceByKey(func)
  • func固定:((curr,agg)=>curr+agg)

2.示例

sc.parallelize(Seq(("a", 1), ("a", 1), ("b", 1)))
  .reduceByKey( (curr, agg) => curr + agg )
  .collect()

在这里插入图片描述

groupByKey

1.使用场景

GroupByKey 算子的主要作用是按照 Key 分组, 和 ReduceByKey 有点类似, 但是 GroupByKey 并不求聚合, 只是列举 Key 对应的所有 Value

2.示例

sc.parallelize(Seq(("a", 1), ("a", 1), ("b", 1)))
  .groupByKey()
  .collect()

在这里插入图片描述

combineByKey

使用场景

  1. 对数据集按照 Key 进行聚合
  2. combineByKey(createCombiner, mergeValue, mergeCombiners, [partitioner], [mapSideCombiner], [serializer])
  3. 参数:
    createCombiner 将 Value 进行初步转换,就是把value值变为元组,赋予一个初始词频1,这个他只作用于第一条数据
    mergeValue 在每个分区把上一步转换的结果,于未转化的结果聚合,每聚合一条词频加1最终得到分区结果
    mergeCombiners 再把所有的分区结果基础上把相同k的分区结果的聚合得到我们的最终结果
    后三个是有默认值的:
    partitioner 分区方式
    mapSideCombiner 控制是否在Map端进行Combine
    serializer 序列化器

示例

val rdd = sc.parallelize(Seq(
  ("zhangsan", 99.0),
  ("zhangsan", 96.0),
  ("lisi", 97.0),
  ("lisi", 98.0),
  ("zhangsan", 97.0))
)
//求每个人的平均数(总分数/科目数)
val combineRdd = rdd.combineByKey(
  createcombiner = score => (score, 1),
  mergeValue = (scoreCount: (Double, Int),newScore) => (scoreCount._1 + newScore, scoreCount._2 + 1),
  mergeCombines = 
  (scoreCount1: (Double, Int), scoreCount2: (Double, Int)) =>
    (scoreCount1._1 + scoreCount2._1, scoreCount1._2 + scoreCount2._2)
) //scorecount1:是传入值curr,scorecount2是累加结果agg
//("张三",(99+96+97,3))
val meanRdd = combineRdd.map(score => (score._1, score._2._1 / score._2._2))

meanRdd.collect()

在这里插入图片描述
在这里插入图片描述

flodByKey

1.使用场景

他与reduceByKey逻辑相同,唯一不同是使用柯里化可以对初始值进行定义.他的初始值作用是对curr进行设置,设定5,curr就相应的加5
foldByKey(zeroValue)(func)
参数
zeroValue 初始值
func固定为: ((curr,age)=>curr+age)

2.示例

sc.parallelize(Seq(("a", 1), ("a", 1), ("b", 1)))
  .foldByKey(zeroValue = 10)( (curr, agg) => curr + agg )
  .collect()

在这里插入图片描述

aggregateByKey

1.使用场景

  • 特别适合的场景是先处理后聚合
  • rdd.aggregateByKey(zeroValue)(seqOp, combOp)
  • 参数
    zeroValue 指定初始值
    seqOp (初始值,集合中的数值)=>方法体就是初始值和集合中的数据进行数学运行
    comboOp 将seqOp处理过的结果进行聚合

2.示例

val rdd = sc.parallelize(Seq(("手机", 10.0), ("手机", 15.0), ("电脑", 20.0)))
val result = rdd.aggregateByKey(0.8)(
  seqOp = (zero, price) => price * zero,
  combOp = (curr, agg) => curr + agg
).collect()
println(result)

在这里插入图片描述在这里插入图片描述

join

1.使用场景

将两个 RDD 按照相同的 Key 进行连接(两个rdd的k放入到一个元组中)
join(other, [partitioner or numPartitions])

2.示例

val rdd1 = sc.parallelize(Seq(("a", 1), ("a", 2), ("b", 1)))
val rdd2 = sc.parallelize(Seq(("a", 10), ("a", 11), ("a", 12)))

rdd1.join(rdd2).collect()

在这里插入图片描述

排序sortBy,sortBykey

1.使用场景

  • sortBy(func, ascending, numPartitions)
  • 参数
    func通过这个函数返回要排序的字段
    以下有默认值:
    ascending是否升序
    numPartitions分区数
  • 注意点
    1. 普通的 RDD 没有sortByKey, 只有 Key-Value 的 RDD 才有
    2. sortBy可以指定按照哪个字段来排序, sortByKey直接按照 Key 来排序

2.示例

val rdd1 = sc.parallelize(Seq(("a", 3), ("b", 2), ("c", 1)))
val sortByResult = rdd1.sortBy( item => item._2 ).collect() //指定字段
val sortByKeyResult = rdd1.sortByKey().collect()

println(sortByResult)
println(sortByKeyResult)

改变分区数:coalesce,repartitioin

1.使用场景

repartitioin(numPartitions)进行分区的时候默认是Shuffle的
coalesce(numPartitions, shuffle)进行分区的时候默认是不Shuffle的,默认不能增大分区数
对于coalesce(numPartitions, shuffle)如果新的分区数量比原分区数大, 必须 Shuffled, 否则重分区无效

2.示例

val rdd = sc.parallelize(Seq(("a", 3), ("b", 2), ("c", 1)))
val oldNum = rdd.partitions.length

val coalesceRdd = rdd.coalesce(4, shuffle = true)
val coalesceNum = coalesceRdd.partitions.length //partitions分区数

val repartitionRdd = rdd.repartition(4)
val repartitionNum = repartitionRdd.partitions.length

print(oldNum, coalesceNum, repartitionNum)

updateStateByKey

k不动,对value值进行实时累加

.updateStateByKey((currValues: Seq[Int], state: Option[Int]) => {
      var count = currValues.sum[当前批次数据求和] + state.getOrElse(0)[前面所有批次数据结果值];
      Some(count)
    })
[1    currvalues.sum=6  存入 Opetin=6
2
3]
[1 currValues.sum=3+6=9 存入Option=9
1
1]

注意:使用此算子必须要进行checkpoint检查点设置
为什么设置checkpoint,当计算失败了,数据可以临时保存在检查点,下次计算可以续上.

Action算子

collect,first,take,takeSample获取数据

1.使用场景

  • first()
    返回第一个元素
  • take(N)
    返回前N个元素
  • takeSample(withReplacement, num,send))
    抽样采样获取数据
    withReplacement, true有放回,false无放回
    num, 取样几个
    send随机种子,可以不传
  • collect
    以数组的形式返回数据集中所有元素

2.示例

rdd1.first()
rdd1.take(10)
rdd1.takeSample(withRepacement=true,num=3)
rdd1.collect()

reduce()

1.使用场景

对整个结果集规约, 最终生成一条数据, 是整个数据集的汇总
reduce( (curr一整条数据, agg) ⇒ (“自定义”,curr的k值+agg的k值)) )
返回一个元组

2.reduceByKey和reduce有什么区别:

1.reduce是一个Action算子,reduceByKey是一个转换算子
2.reduceByKey本质上是先按照Key分组,然后把每组聚合
3.reduce是针对一整个数据集来进行聚合
4.reduceByKey是Shuffle操作,先通过Partitoner函数指定分区规则(ByKey指定键),对数据进行分区,在在分区内进行聚合,最后返回多个值
而reduce不涉及Shuffle操作,得到多个分区数据后,对其进行统一的聚合,最后返回一个元组值

3.示例

val rdd = sc.parallelize(Seq(("手机", 10.0), ("手机", 15.0), ("电脑", 20.0)))
val result = rdd.reduce((curr, agg) => ("总价", curr._2 + agg._2))
println(result)

foreach()

1.使用场景

foreach( T ⇒ …​ )遍历每一个元素

2.示例

val rdd = sc.parallelize(List(1,3,4))
sc.foreach(item=>println(item))

count(),countByKey()求数量

1.使用场景

主要用于:数据倾斜,如果要解决数据倾斜的问题,是不是要先知道谁倾斜,通过countByKey可以查看Key对应的数据总数,从而解决数据倾斜

  • count()
    返回集合中元素个数
  • countByKey()
    返回Map映射,求得整个数据集中 Key 以及对应 Key 出现的次数

2.示例

val rdd = sc.parallelize(Seq(("a",1),("a",1),("c",3),("d",4))
println(rdd.count())
println(rdd.countByCount())

在这里插入图片描述

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值