除了逐行处理数据的udf,还有比较常见的就是聚合多行处理udaf,自定义聚合函数。类比rdd编程就是map和reduce算子的区别。
自定义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(用户自定义聚合函数)求众数的更多相关文章

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

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

  2. hive学习笔记之十:用户自定义聚合函数(UDAF)

    欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本篇概览 本文是<hive学习笔记>的第十 ...

  3. 【Spark篇】---SparkSQL中自定义UDF和UDAF,开窗函数的应用

    一.前述 SparkSQL中的UDF相当于是1进1出,UDAF相当于是多进一出,类似于聚合函数. 开窗函数一般分组取topn时常用. 二.UDF和UDAF函数 1.UDF函数 java代码: Spar ...

  4. 【Spark-SQL学习之三】 UDF、UDAF、开窗函数

    环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 jdk1.8 scala-2.10.4(依赖jdk1.8) spark ...

  5. SQL Server 2008 R2——PIVOT 行转列 以及聚合函数的选择

    ==================================声明================================== 本文原创,转载在正文中显要的注明作者和出处,并保证文章的完 ...

  6. 2、SQL基础整理(聚合函数)

    聚合函数 --求平均 select  AVG(age) as 年龄 from xuesheng select AVG(chinese) as 语文 from xuesheng where class ...

  7. Hive学习之自己定义聚合函数

    Hive支持用户自己定义聚合函数(UDAF),这样的类型的函数提供了更加强大的数据处理功能. Hive支持两种类型的UDAF:简单型和通用型.正如名称所暗示的,简单型UDAF的实现很easy,但因为使 ...

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

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

  9. Mongodb学习笔记四(Mongodb聚合函数)

    第四章 Mongodb聚合函数 插入 测试数据 ;j<;j++){ for(var i=1;i<3;i++){ var person={ Name:"jack"+i, ...

随机推荐

  1. numpy 随机产生数字

    python数据分析的学习和应用过程中,经常需要用到numpy的随机函数,由于随机函数random的功能比较多,经常会混淆或记不住,下面我们一起来汇总学习下. 1 numpy.random.rand( ...

  2. OpenCV + python 实现人脸检测(基于照片和视频进行检测)

    OpenCV + python 实现人脸检测(基于照片和视频进行检测) Haar-like 通俗的来讲,就是作为人脸特征即可. Haar特征值反映了图像的灰度变化情况.例如:脸部的一些特征能由矩形特征 ...

  3. JTable动态刷新数据

    http://www.cnblogs.com/fnlingnzb-learner/p/6025408.html 注意下面几个方法的应用场景,不限于JTable,其他swing组件一样 ———————— ...

  4. Nginx+Keepalived+Tomcat高可用负载均衡,Zookeeper集群配置,Mysql(MariaDB)搭建,Redis安装,FTP配置

    JDK 安装步骤 下载 http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html rpm ...

  5. YII2 使用phpexcel(干货)

    参考:http://www.cnblogs.com/xiaocongjiejie/p/5106249.html http://www.cnblogs.com/xiaocongjiejie/p/5106 ...

  6. ubuntu下同时安装anaconda2与anaconda3,并分别安装与之对应的软件

    1.安装anaconda2 参考网址:https://www.cnblogs.com/chamie/p/8876271.html 2.安装anaconda3 转载:https://blog.csdn. ...

  7. A股滚动净利润增速最高排名

    最近2年(共8个季度)的滚动净利润都在增长,且平均增速超过10%. 计算举例:滚动净利润增速 = ((2018Q1 到 2018Q4的净利润之和) / (2017Q4 到 2018Q3的净利润之和) ...

  8. python sort和sorted区别。

    前者是方法,后者是函数.oop和opp区别的经典体现.好好领会,就能知道什么时候写类什么时候写函数好.

  9. 利用PowerShell监控Win-Server性能

    Q:如何系统层面的去监控一下Windows Server? A:额……一时间的话……能想到的可能也就是PowerShell+SQL Server+job,试试. 1.关于PowerShell 2.Po ...

  10. Elasticsearch学习之有用博客

    推荐阅读:1.阿里:https://elasticsearch.cn/article/61712.滴滴:http://t.cn/EUNLkNU3.腾讯:http://t.cn/E4y9ylL4.携程: ...