sparksql 自定义用户函数(UDF)
自定义用户函数有两种方式,区别:是否使用强类型,参考demo:https://github.com/asker124143222/spark-demo
1、不使用强类型,继承UserDefinedAggregateFunction
package com.home.spark import org.apache.spark.SparkConf
import org.apache.spark.sql.{DataFrame, Row, SparkSession}
import org.apache.spark.sql.expressions.{MutableAggregationBuffer, UserDefinedAggregateFunction}
import org.apache.spark.sql.types._ object Ex_sparkUDAF {
def main(args: Array[String]): Unit = {
val conf = new SparkConf(true).setAppName("spark udf").setMaster("local[*]")
val spark = SparkSession.builder().config(conf).getOrCreate() //自定义聚合函数
//创建聚合函数对象
val myUdaf = new MyAgeAvgFunc //注册自定义函数
spark.udf.register("ageAvg",myUdaf) //使用聚合函数
val frame: DataFrame = spark.read.json("input/userinfo.json")
frame.createOrReplaceTempView("userinfo")
spark.sql("select ageAvg(age) from userinfo").show() spark.stop()
}
} //声明自定义函数
//实现对年龄的平均,数据如:{ "name": "tom", "age" : 20}
class MyAgeAvgFunc extends UserDefinedAggregateFunction {
//函数输入的数据结构,本例中只有年龄是输入数据
override def inputSchema: StructType = {
new StructType().add("age", LongType)
} //计算时的数据结构(缓冲区)
// 本例中有要计算年龄平均值,必须有两个计算结构,一个是年龄总计(sum),一个是年龄个数(count)
override def bufferSchema: StructType = {
new StructType().add("sum", LongType).add("count", LongType)
} //函数返回的数据类型
override def dataType: DataType = DoubleType //函数是否稳定
override def deterministic: Boolean = true //计算前缓冲区的初始化,结构类似数组,这里缓冲区与之前定义的bufferSchema顺序一致
override def initialize(buffer: MutableAggregationBuffer): Unit = {
//sum
buffer(0) = 0L
//count
buffer(1) = 0L
} //根据查询结果更新缓冲区数据,input是每次进入的数据,其数据结构与之前定义的inputSchema相同
//本例中每次输入的数据只有一个就是年龄
override def update(buffer: MutableAggregationBuffer, input: Row): Unit = {
if(input.isNullAt(0)) return
//sum
buffer(0) = buffer.getLong(0) + input.getLong(0) //count,每次来一个数据加1
buffer(1) = buffer.getLong(1) + 1
} //将多个节点的缓冲区合并到一起(因为spark是分布式的)
override def merge(buffer1: MutableAggregationBuffer, buffer2: Row): Unit = {
//sum
buffer1(0) = buffer1.getLong(0) + buffer2.getLong(0) //count
buffer1(1) = buffer1.getLong(1) + buffer2.getLong(1)
} //计算最终结果,本例中就是(sum / count)
override def evaluate(buffer: Row): Any = {
buffer.getLong(0).toDouble / buffer.getLong(1)
}
}
2、使用强类型,
package com.home.spark import org.apache.spark.SparkConf
import org.apache.spark.sql._
import org.apache.spark.sql.expressions.Aggregator object Ex_sparkUDAF2 {
def main(args: Array[String]): Unit = {
val conf = new SparkConf(true).setAppName("spark udf class").setMaster("local[*]")
val spark = SparkSession.builder().config(conf).getOrCreate() //rdd转换成df或者ds需要SparkSession实例的隐式转换
//导入隐式转换,注意这里的spark不是包名,而是SparkSession的对象名
import spark.implicits._ //创建聚合函数对象
val myAvgFunc = new MyAgeAvgClassFunc
val avgCol: TypedColumn[UserBean, Double] = myAvgFunc.toColumn.name("avgAge")
val frame = spark.read.json("input/userinfo.json")
val userDS: Dataset[UserBean] = frame.as[UserBean]
//应用函数
userDS.select(avgCol).show() spark.stop()
}
} case class UserBean(name: String, age: BigInt) case class AvgBuffer(var sum: BigInt, var count: Int) //声明用户自定义函数(强类型方式)
//继承Aggregator,设定泛型
//实现方法
class MyAgeAvgClassFunc extends Aggregator[UserBean, AvgBuffer, Double] {
//初始化缓冲区
override def zero: AvgBuffer = {
AvgBuffer(0, 0)
} //聚合数据
override def reduce(b: AvgBuffer, a: UserBean): AvgBuffer = {
if(a.age == null) return b
b.sum = b.sum + a.age
b.count = b.count + 1 b
} //缓冲区合并操作
override def merge(b1: AvgBuffer, b2: AvgBuffer): AvgBuffer = {
b1.sum = b1.sum + b2.sum
b1.count = b1.count + b2.count b1
} //完成计算
override def finish(reduction: AvgBuffer): Double = {
reduction.sum.toDouble / reduction.count
} override def bufferEncoder: Encoder[AvgBuffer] = Encoders.product override def outputEncoder: Encoder[Double] = Encoders.scalaDouble
}
继承Aggregator
sparksql 自定义用户函数(UDF)的更多相关文章
- Sqlserver如何递归查询层级数据将父级字段和本级某个字段合并?如何自定义用户函数并调用?
		
开门见山,首先说下遇到的问题:前期系统地区字典表中,每个省市县只存了本级名称,没存完整的字段.如:肥西县隶属安徽省合肥市,表中就存了一个肥西县.现有需求需要将完整字段显示,由于系统已在线上运营,无法做 ...
 - 048 SparkSQL自定义UDAF函数
		
一:程序 1.需求 实现一个求平均值的UDAF. 这里保留Double格式化,在完成求平均值后与系统的AVG进行对比,观察正确性. 2.SparkSQLUDFDemo程序 package com.sc ...
 - Spark(十三)SparkSQL的自定义函数UDF与开窗函数
		
一 自定义函数UDF 在Spark中,也支持Hive中的自定义函数.自定义函数大致可以分为三种: UDF(User-Defined-Function),即最基本的自定义函数,类似to_char,to_ ...
 - SparkSQL中的自定义函数UDF
		
在Spark中,也支持Hive中的自定义函数.自定义函数大致可以分为三种: UDF(User-Defined-Function),即最基本的自定义函数,类似to_char,to_date等 UDAF( ...
 - Spark(十三)【SparkSQL自定义UDF/UDAF函数】
		
目录 一.UDF(一进一出) 二.UDAF(多近一出) spark2.X 实现方式 案例 ①继承UserDefinedAggregateFunction,实现其中的方法 ②创建函数对象,注册函数,在s ...
 - java mysql自定义函数UDF之调用c函数
		
正如sqlite可以定义自定义函数,它是通过API定义c函数的,不像其他,如这里的mysql.sqlite提供原生接口就可以方便的调用其他语言的方法,同样的mysql也支持调用其它语言的方法. goo ...
 - 10_Hive自定义函数UDF
		
Hive官方的UDF手册地址是:https://cwiki.apache.org/confluence/display/Hive/LanguageManual+UDF 1.使用内置函数的快捷方法: 创 ...
 - hive自定义函数UDF UDTF UDAF
		
Hive 自定义函数 UDF UDTF UDAF 1.UDF:用户定义(普通)函数,只对单行数值产生作用: UDF只能实现一进一出的操作. 定义udf 计算两个数最小值 public class Mi ...
 - T-SQL: 17 个与日期时间相关的自定义函数(UDF),周日作为周的最后一天,均不受 @@DateFirst、语言版本影响!
		
原文:T-SQL: 17 个与日期时间相关的自定义函数(UDF),周日作为周的最后一天,均不受 @@DateFirst.语言版本影响! CSDN 的 Blog 太滥了!无时不刻地在坏! 开始抢救性搬家 ...
 
随机推荐
- note2
 - Delphi Win API 函数 [ ShellAPI ] ShellExecute 函数
			
引用单元:uses ShellAPI; 函数原型:function ShellExecute(hWnd: HWND; Operation, FileName, Parameters,Directory ...
 - 英语单词Permissive
			
Permissive 来源 [root@centos7 ~]# setenforce usage: setenforce [ Enforcing | Permissive | | ] 翻译 adj. ...
 - 第一次用angularJS做后台管理点滴
			
很早以前就大概看过一点angualrjs,但是没有项目,一直没有进行下去,就是干巴巴的看着,过了一段时间发现什么也不记得了. 来yulebaby我的第一个后台管理是用easyui做的,做完那个以后发现 ...
 - SPOJ - FTOUR2   (点分治+树状数组)
			
题目:https://vjudge.net/contest/307753#problem/I 题意:有一颗树,上面有白色黑色点,每个点上有一个权值,权值可以为负,现在我要求一条路径,权值和最大,这条路 ...
 - redis.conf 配置文件介绍
			
1: Redis默认不是以守护进程的方式运行,可以通过该配置项修改,使用yes启用守护进程 daemonize no 2: 当Redis以守护进程方式运行时,Redis默认会把pid写入/var/ru ...
 - git分支回退以及目录回退
			
分支回退 git checkout - 目录回退 cd -
 - 转载:AWR介绍使用
			
转载自 http://www.cnblogs.com/lanzi/archive/2011/03/07/1975096.html 自动工作负载库(Automatic Workload Reposito ...
 - jmeter 测试结果分析术语
			
label:定义http请求名称. samples:测试中一共发出的请求. average:平均响应时长.默认是单个request的平均响应时长. median:中位数,50%用户的响应时长. 90% ...
 - 工控PLC中,关于定时器TON,TOF,的一点新认知,或者说醒悟吧!
			
PLC 中的定时器,都是放在一个具体PRG任务单元中的,而PRG单元需要放在具体固定的周期循环任务中才能被执行,而这个周期循环任务的循环周期 T: 与定时器的定时时间T0: T与T0 的数量级 ...