一.简介

  Spark的自定义udf和udaf是为了提供函数扩展,Spark本身提供了几十上百个算子,在数据分析的各个方面的常用计算方式都有提到,但计算场景千差万别,算子也不会面面俱到,如何在单机或集群上定义函数就是要重点关注的地方。特别是在集群模式中,函数需要使用spark注册才能在各个节点上使用,因此,udf和udaf就显得比较重要了。

二.设置日志级别

Logger.getLogger("org").setLevel(Level.WARN) // 设置日志级别为WARN

三.创建spark入口

val spark = SparkSession.builder().appName("UdfUdaf").master("local[2]").getOrCreate()
val sc = spark.sparkContext
val sqlContext = spark.sqlContext

四.创建测试数据

val userData = Array(
"2015,11,www.baidu.com", "2016,14,www.google.com",
"2017,13,www.apache.com", "2015,21,www.spark.com",
"2016,32,www.hadoop.com", "2017,18,www.solr.com",
"2017,14,www.hive.com"
) val userDataRDD = sc.parallelize(userData) // 转化为RDD
val userDataType = userDataRDD.map(line => {
val Array(age, id, url) = line.split(",")
Row(age, id.toInt, url)
})
val structTypes = StructType(Array(
StructField("age", StringType, true),
StructField("id", IntegerType, true),
StructField("url", StringType, true)
))
// RDD转化为DataFrame
val userDataFrame = sqlContext.createDataFrame(userDataType,structTypes)
// 注冊临时表
userDataFrame.createOrReplaceTempView("udf")

五.自定义udf并测试

def isAdult(age : Int) ={
if(age > 18){
true
}else{
false
}
}
// 注册udf(方式一)
spark.udf.register("isAdult_1", (id : Int) => if(id > 18) true else false) // 匿名函数
// 注册udf(方式二)
spark.udf.register("isAdult_2", isAdult _) // 预先定义好的普通函数
// 验证udf方式一
val result_1 = sqlContext.sql("select * from udf where isAdult_1(udf.id)")
result_1.show(false)
// 验证udf方式二
val result_2 = sqlContext.sql("select * from udf where isAdult_2(udf.id)")
result_2.show(false)

六.执行结果

  

七.自定义udaf并测试

object AverageUserDefinedAggregateFunction extends UserDefinedAggregateFunction{
//聚合函数输入数据结构
override def inputSchema:StructType = StructType(StructField("input", LongType) :: Nil)
//缓存区数据结构
override def bufferSchema: StructType = StructType(StructField("sum", LongType) :: StructField("count", LongType) :: Nil)
//结果数据结构
override def dataType : DataType = DoubleType
// 是否具有唯一性
override def deterministic : Boolean = true
//初始化
override def initialize(buffer : MutableAggregationBuffer) : Unit = {
buffer(0) = 0L
buffer(1) = 0L
}
//数据处理 : 必写,其它方法可选,使用默认
override def update(buffer: MutableAggregationBuffer, input: Row): Unit = {
if(input.isNullAt(0)) return
buffer(0) = buffer.getLong(0) + input.getLong(0) //求和
buffer(1) = buffer.getLong(1) + 1 //计数
}
//合并
override def merge(bufferLeft: MutableAggregationBuffer, bufferRight: Row): Unit ={
bufferLeft(0) = bufferLeft.getLong(0) + bufferRight.getLong(0)
bufferLeft(1) = bufferLeft.getLong(1) + bufferRight.getLong(1)
}
//计算结果
override def evaluate(buffer: Row): Any = buffer.getLong(0).toDouble / buffer.getLong(1)
}
    /**
* 测试udaf
*/
spark.udf.register("average", AverageUserDefinedAggregateFunction)
spark.sql("select count(*) count,average(age) avg_age from udf").show(false)

八.执行结果

  

Spark之UDAF的更多相关文章

  1. Spark SQL UDAF示例

    UDAF:用户自定义聚合函数 Scala 2.10.7,spark 2.0.0 package UDF_UDAF import java.util import org.apache.spark.Sp ...

  2. Spark笔记之使用UDAF(User Defined Aggregate Function)

    一.UDAF简介 先解释一下什么是UDAF(User Defined Aggregate Function),即用户定义的聚合函数,聚合函数和普通函数的区别是什么呢,普通函数是接受一行输入产生一个输出 ...

  3. Kafka:ZK+Kafka+Spark Streaming集群环境搭建(十五)Spark编写UDF、UDAF、Agg函数

    Spark Sql提供了丰富的内置函数让开发者来使用,但实际开发业务场景可能很复杂,内置函数不能够满足业务需求,因此spark sql提供了可扩展的内置函数. UDF:是普通函数,输入一个或多个参数, ...

  4. Spark Sql的UDF和UDAF函数

    Spark Sql提供了丰富的内置函数供猿友们使用,辣为何还要用户自定义函数呢?实际的业务场景可能很复杂,内置函数hold不住,所以spark sql提供了可扩展的内置函数接口:哥们,你的业务太变态了 ...

  5. spark编写UDF和UDAF

    UDF: 一.编写udf类,在其中定义udf函数 package spark._sql.UDF import org.apache.spark.sql.functions._ /** * AUTHOR ...

  6. spark自定义函数之——UDAF使用详解及代码示例

    UDAF简介 UDAF(User Defined Aggregate Function)即用户定义的聚合函数,聚合函数和普通函数的区别是什么呢,普通函数是接受一行输入产生一个输出,聚合函数是接受一组( ...

  7. 【转】Spark-Sql版本升级对应的新特性汇总

    Spark-Sql版本升级对应的新特性汇总 SparkSQL的前身是Shark.由于Shark自身的不完善,2014年6月1日Reynold Xin宣布:停止对Shark的开发.SparkSQL抛弃原 ...

  8. 转:Spark User Defined Aggregate Function (UDAF) using Java

    Sometimes the aggregate functions provided by Spark are not adequate, so Spark has a provision of ac ...

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

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

随机推荐

  1. [Linux][Mac]如何使用SSH登陆远程Linux服务器&使用SCP下载远程终端文件

    --------------------------- 2017-01-16 初版 2017-01-17 增加ssh登录端口修改 -------------------------- 一.使用ssh ...

  2. [java核心外篇]__Object类与对象类型的转型

    前言 我们在之前的学习中提过很多次了,java是面向对象的,java的基础可以说是建立在类和对象上面的.然后我们又学到了类的继承,发现了在java类库中,类的继承是极为普遍的,一个类继承另一个类,就像 ...

  3. 代理模式(静态代理、JDK动态代理原理分析、CGLIB动态代理)

    代理模式 代理模式是设计模式之一,为一个对象提供一个替身或者占位符以控制对这个对象的访问,它给目标对象提供一个代理对象,由代理对象控制对目标对象的访问. 那么为什么要使用代理模式呢? 1.隔离,客户端 ...

  4. EntityFramework中对象的状态管理(笔记)

    刚开始接触EF框架的时候总是不明白: 为什么查询出来的对象 Remove().再 SaveChanges()就会把数据删除.而自己 new 一个Person()对象,然后 Remove()不行? 为什 ...

  5. 开源任务调度平台elastic-job-lite源码解析

    前段时间写过一遍文章<一文揭秘定时任务调度框架quartz>,有读者建议我再讲讲elastic-job这个任务调度框架,年末没有那么忙,就来学习一下elastic-job. 首先一点,el ...

  6. go捕获Ctrl+C信号

    我们希望当服务器接收到一个 SIGTERM 信号时能够自动关机,或者做一些善后的操作,以下是实现的方法 package main import ( "os" "os/si ...

  7. 第12章 Linux配置定时任务详解

    12.1 配置定时任务 首先需弄清的概念: (1).crond是一个daemon类程序,路径为/usr/sbin/crond.默认会以后台方式启动,service或systemd方式启动crond默认 ...

  8. Ansible常用模块介绍及使用(week5_day1_part2)--技术流ken

    Ansible模块 在上一篇博客<Ansible基础认识及安装使用详解(一)--技术流ken>中以及简单的介绍了一下ansible的模块.ansible是基于模块工作的,所以我们必须掌握几 ...

  9. MySQL之实现Oracle中的rank()函数的功能

      假设表格为student, 数据如下:   我们要在MySQL中实现Oracle中的rank()函数功能,即组内排序,具体来说: 就是对student表中按照课程(course)对学生(name) ...

  10. 让MySQL查询更加高效——对查询进行重构

    在优化有问题的查询时,目标应该是找到一个更优的方法获得实际需要的结果,而不是一定总是要求从MySQL获取一模一样的结果集 一个复杂查询还是多个简单查询 设计查询的时候一定需要考虑的问题就是,是否需要将 ...