UDAF(用户自定义聚合函数)求众数
自定义UDAF,需要extends org.apache.spark.sql.expressions.UserDefinedAggregateFunction,并实现接口中的8个方法。
udaf写起来比较麻烦,我下面列一个之前写的取众数聚合函数,在我们通常在聚合统计的时候可能会受某条脏数据的影响。
举个栗子:
对于一个app日志聚合的时候,有id与ip,原则上一个id有一个ip,但是在多条数据里有一条ip是错误的或者为空的,这时候group能会聚合成两条数据了就,如果使用max,min对ip也进行聚合,那也不太合理,这时候可以进行投票,去类似多数对结果,从而聚合后只有一个设备。
废话少说,上代码:
import org.apache.spark.sql.Row
import org.apache.spark.sql.expressions.{MutableAggregationBuffer, UserDefinedAggregateFunction}
import org.apache.spark.sql.types._ /**
* Description: 自定义聚合函数:众数(取列内频率最高的一条)
*/ class UDAFGetMode extends UserDefinedAggregateFunction {
override def inputSchema: StructType = {
StructType(StructField("inputStr", StringType, true) :: Nil)
} override def bufferSchema: StructType = {
StructType(StructField("bufferMap", MapType(keyType = StringType, valueType = IntegerType), true) :: Nil)
} override def dataType: DataType = StringType override def deterministic: Boolean = false //初始化map
override def initialize(buffer: MutableAggregationBuffer): Unit = {
buffer() = scala.collection.immutable.Map[String, Int]()
} //如果包含这个key则value+1,否则写入key,value=1
override def update(buffer: MutableAggregationBuffer, input: Row): Unit = {
val key = input.getAs[String]()
val immap = buffer.getAs[Map[String, Int]]()
val bufferMap = scala.collection.mutable.Map[String, Int](immap.toSeq: _*)
val ret = if (bufferMap.contains(key)) {
// val new_value = bufferMap.get(key).get + 1
val new_value = bufferMap(key) +
bufferMap.put(key, new_value)
bufferMap
} else {
bufferMap.put(key, )
bufferMap
}
buffer.update(, ret) } override def merge(buffer1: MutableAggregationBuffer, buffer2: Row): Unit = {
//合并两个map 相同的key的value累加
val tempMap = (buffer1.getAs[Map[String, Int]]() /: buffer2.getAs[Map[String, Int]]()) {
case (map, (k, v)) => map + (k -> (v + map.getOrElse(k, )))
}
buffer1.update(, tempMap)
} override def evaluate(buffer: Row): Any = {
//返回值最大的key
var max_value =
var max_key = ""
buffer.getAs[Map[String, Int]]().foreach({ x =>
val key = x._1
val value = x._2
if (value > max_value) {
max_value = value
max_key = key
}
})
max_key
}
}
测试类:
object UDAFTest {
def main(args: Array[String]): Unit = {
val spark = SparkSession.builder().master("local").appName(this.getClass.getSimpleName).getOrCreate()
spark.udf.register("get_mode", new UDAFGetMode)
import spark.implicits._
val df = Seq(
(, "10.10.1.1", "start"),
(, "10.10.1.1", "search"),
(, "123.123.123.1", "search"),
(, "10.10.1.0", "stop"),
(, "123.123.123.1", "start")
).toDF("id", "ip", "action")
df.createTempView("tb")
spark.sql(s"select id,get_mode(ip) as u_ip,count(*) as cnt from tb group by id").show()
}
}
UDAF(用户自定义聚合函数)求众数的更多相关文章
- Spark SQL 用户自定义函数UDF、用户自定义聚合函数UDAF 教程(Java踩坑教学版)
在Spark中,也支持Hive中的自定义函数.自定义函数大致可以分为三种: UDF(User-Defined-Function),即最基本的自定义函数,类似to_char,to_date等 UDAF( ...
- hive学习笔记之十:用户自定义聚合函数(UDAF)
欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本篇概览 本文是<hive学习笔记>的第十 ...
- 【Spark篇】---SparkSQL中自定义UDF和UDAF,开窗函数的应用
一.前述 SparkSQL中的UDF相当于是1进1出,UDAF相当于是多进一出,类似于聚合函数. 开窗函数一般分组取topn时常用. 二.UDF和UDAF函数 1.UDF函数 java代码: Spar ...
- 【Spark-SQL学习之三】 UDF、UDAF、开窗函数
环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 jdk1.8 scala-2.10.4(依赖jdk1.8) spark ...
- SQL Server 2008 R2——PIVOT 行转列 以及聚合函数的选择
==================================声明================================== 本文原创,转载在正文中显要的注明作者和出处,并保证文章的完 ...
- 2、SQL基础整理(聚合函数)
聚合函数 --求平均 select AVG(age) as 年龄 from xuesheng select AVG(chinese) as 语文 from xuesheng where class ...
- Hive学习之自己定义聚合函数
Hive支持用户自己定义聚合函数(UDAF),这样的类型的函数提供了更加强大的数据处理功能. Hive支持两种类型的UDAF:简单型和通用型.正如名称所暗示的,简单型UDAF的实现很easy,但因为使 ...
- Kafka:ZK+Kafka+Spark Streaming集群环境搭建(十五)Spark编写UDF、UDAF、Agg函数
Spark Sql提供了丰富的内置函数让开发者来使用,但实际开发业务场景可能很复杂,内置函数不能够满足业务需求,因此spark sql提供了可扩展的内置函数. UDF:是普通函数,输入一个或多个参数, ...
- Mongodb学习笔记四(Mongodb聚合函数)
第四章 Mongodb聚合函数 插入 测试数据 ;j<;j++){ for(var i=1;i<3;i++){ var person={ Name:"jack"+i, ...
随机推荐
- go get fatal: could not read Username for 'https://code.xxx.org': terminal prompts disabled
用go get下载私有代码库的时候,莫名其妙产生了以下错误,公有代码库没有影响. chenchideMacBook-Pro:~ chenchi$ go get code.xxx.org/adarch/ ...
- 解决MAMP启动mysql服务 但是Navicat连接不上
问题重现 错误信息 2003 - Can't connect to MySQL server on '127.0.0.1' (61 "Connection refused") 解决 ...
- 关于Retrofit网络请求URL中含有可变参数的处理
开题:在此默认各位看官对Retrofit.以及Okhttp已经有过一定的了解及应用,所以今天我们不谈基础入门的东西,今天我们谈在Retrofit请求接口管理类中URL参数含有动态参数的处理方式.一般我 ...
- c++ 异常 warning: 'MEMORY_UNIT_NAME' defined but not used
是开关的问题 , 将 #-g -O2 -pipe -W -Wall -Werror -fPIC -Wno-deprecated c++ 去掉.不检查.
- Android 查看蓝牙hci日志
最近在调试android连接ble设备,需要查看hci日志.记录一下方法. 1. 开发者选项->启用蓝牙HCI信息收集日志. 2. android 8版本,默认位置/data/misc/blue ...
- 在生成一个窗体的时候,点击窗体的右上角关闭按钮激发窗体事件的方法:窗体Frame为事件源,WindowsListener接口调用Windowsclosing()。
事件模式的实现步骤: 开发事件对象(事件发送者)——接口——接口实现类——设置监听对象 一定要理解透彻Gril.java程序. 重点:学会处理对一个事件源有多个事件的监听器(在发送消息时监听器收到 ...
- fiddler使用指南
fiddler使用指南 fiddler 设置 如果要手机抓包的话,需要设置fiddler, 允许远程设备连接 tools/fiddler options/connection/allow remote ...
- 图像的下采样Subsampling 与 上采样 Upsampling
I.目的 缩小图像(或称为下采样(subsampled)或降采样(downsampled))的主要目的: 1.使得图像符合显示区域的大小: 2.生成对应图像的缩略图. 放大图像(或称为上采样(ups ...
- JS -- serializeJSON
http://www.cnblogs.com/linzenews/p/7065050.html
- WEB服务器与应用服务器的区别
一.简述 WEB服务器与应用服务器的区别: 1.WEB服务器: 理解WEB服务器,首先要理解什么是WEB?WEB可以简单理解为我们所看到的HTML页面就是WEB的数据元素,处理这些数据元素的应用软件就 ...