SparkSQL自定义强类型聚合函数

        自定义强类型聚合函数跟自定义无类型聚合函数的操作类似,相对的,实现自定义强类型聚合函数则要继承org.apache.spark.sql.expressions.Aggregator。强类型的优点在于:其内部与特定数据集紧密结合,增强了紧密型、安全性,但由于其紧凑的特性,降低了适用性。

准备employ.txt文件:

Michael,3000
Andy,4500
Justin,3500
Betral,4000

一、定义自定义强类型聚合函数

package com.cjs
 
import org.apache.spark.sql.{Encoder, Encoders}
import org.apache.spark.sql.expressions.Aggregator
 
//定义输入数据类型
case class Employee(name:String, salary:Long)
//定义聚合缓冲器类型
case class Average(var sum:Long, var count:Long)
 
//继承Aggregator类时需要指定泛型类型,依次为:传入聚合缓冲器的数据类型、聚合缓冲器的类型、返回结果的类型
object MyAggregator extends Aggregator[Employee, Average, Double]{
    //类似于初始化聚合缓冲器
    override def zero: Average = Average(0L,0L)
 
    //根据传入的参数进行运算操作,最后更新buffer缓冲器,并返回
    override def reduce(buffer: Average, a: Employee): Average = {
        buffer.sum += a.salary
        buffer.count +=1
        buffer
    }
    //b1为主缓冲器,b2为分布式架构中各个节点的缓冲器,对b1和b2的数据进行运算,并返回b1
    override def merge(b1: Average, b2: Average): Average = {
        b1.sum += b2.sum
        b1.count += b2.count
        b1
    }
    //使用主缓冲器的数据进行运算,返回一个运算结果
    override def finish(reduction: Average): Double = {
        reduction.sum.toDouble/reduction.count
    }
    //指定中间值的编码器类型
    override def bufferEncoder: Encoder[Average] = {
        Encoders.product
    }
    //指定最终输出值的编码器类型
    override def outputEncoder: Encoder[Double] = {
        Encoders.scalaDouble
    }
}

二、使用强类型聚合函数

package com.cjs
 
import org.apache.log4j.{Level, Logger}
import org.apache.spark.SparkConf
import org.apache.spark.sql.SparkSession
 
object TestMyAggregator {
    case class Emp(name:String, salary:Long)
    def main(args: Array[String]): Unit = {
        Logger.getLogger("org.apache.spark").setLevel(Level.ERROR)
        val conf = new SparkConf()
            .set("spark.sql.warehouse.dir","file:///e:/tmp/spark-warehouse")
            .set("spark.some.config.option","some-value")
 
        val ss = SparkSession.builder()
            .config(conf)
            .appName("test_myAggregator")
            .master("local[2]")
            .getOrCreate()
 
        val path = "E:\\IntelliJ Idea\\sparkSql_practice\\src\\main\\scala\\com\\cjs\\employee.txt"
 
        val sc = ss.sparkContext
        import ss.implicits._
        val empRDD = sc.textFile(path).map(_.split(",")).map(value=>Emp(value(0),value(1).toLong))
        val ds = empRDD.toDF().as[Employee]
        println("DS结构:")
        ds.printSchema()
        println("DS数据")
        ds.show()
 
        val averSalary = MyAggregator.toColumn.name("aver_salary")  //转换成Column
        val result = ds.select(averSalary)
        println("平均工资:")
        result.show()
        println("DS使用select:")
        ds.select($"name",$"salary").show()
    }
 
}

输出结果:

转载于:https://www.cnblogs.com/SysoCjs/p/11466201.html

Apache Spark 是专为大规模数据处理而设计的快速通用的计算引擎。Spark是UC Berkeley AMP lab (加州大学伯克利分校的AMP实验室)所开源的类Hadoop MapReduce的通用并行框架,Spark,拥有Hadoop MapReduce所具有的优点;但不同于MapReduce的是——Job中间输出结果可以保存在内存中,从而不再需要读写HDFS,因此Spark能更好地适用于数据挖掘与机器学习等需要迭代的MapReduce的算法。Spark 是一种与 Hadoop 相似的开源集群计算环境,但是两者之间还存在一些不同之处,这些有用的不同之处使 Spark 在某些工作负载方面表现得更加优越,换句话说,Spark 启用了内存分布数据集,除了能够提供交互式查询外,它还可以优化迭代工作负载。Spark 是在 Scala 语言中实现的,它将 Scala 用作其应用程序框架。与 Hadoop 不同,SparkScala 能够紧密集成,其中的 Scala 可以像操作本地集合对象一样轻松地操作分布式数据集。尽管创建 Spark 是为了支持分布式数据集上的迭代作业,但是实际上它是对 Hadoop 的补充,可以在 Hadoop 文件系统中并行运行。通过名为 Mesos 的第三方集群框架可以支持此行为。Spark 由加州大学伯克利分校 AMP 实验室 (Algorithms, Machines, and People Lab) 开发,可用来构建大型的、低延迟的数据分析应用程序。本部分内容全面涵盖了Spark生态系统的概述及其编程模型,深入内核的研究,Spark on Yarn,Spark RDD、Spark Streaming流式计算原理与实践,Spark SQL,Spark的多语言编程以及SparkR的原理和运行。本套Spark教程不仅面向项目开发人员,甚至对于研究Spark的在校学员,都是非常值得学习的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值