用户定义的聚合函数(UDAF) 是用户根据自定义公式或业务逻辑定义自己的聚合函数的一种方法。可以使用UDAF来计算输入数据组(于单行相对)的自定义计算。Spark 维护单个AggregationBuffer,它用于存储每组输入数据的中间结果。
若要创建UDAF,必须继承UserDefinedAggregateFunction基类并实现以下方法:
1:inputSchema:用于指定输入参数,输入参数类型为StructType
2:bufferSchema:用于指定UDAF中间结果,中间结果类型为StructType
3:dataType:用于指定返回结果,返回结果的类型为DataType
4:dateministic:是一个布尔值,它指定此UDAF对于某个输入是否会返回相同的结果。
5:initialize:初始化聚合缓冲区的初始值。
6:update:描述应如何根据给定行更行内部缓冲区
7:merge:描述应如何合并两个聚合缓冲区
8:evaluate:将生成聚合最终结果
下面的例子实现了一个BoolAnd ,它将返回(给定列)所有的行是否为true,如果不是,则返回false
import org.apache.spark.sql.expressions.MutableAggregationBuffer
import org.apache.spark.sql.expressions.UserDefinedAggregateFunction
import org.apache.spark.sql.Row
import org.apache.spark.sql.types._
class BoolAnd extends UserDefinedAggregateFunction {
def inputSchema: org.apache.spark.sql.types.StructType =
StructType(StructField("value", BooleanType) :: Nil)
def bufferSchema: StructType = StructType(
StructField("result", BooleanType) :: Nil
)
def dataType: DataType = BooleanType
def deterministic: Boolean = true
def initialize(buffer: MutableAggregationBuffer): Unit = {
buffer(0) = true
}
def update(buffer: MutableAggregationBuffer, input: Row): Unit = {
buffer(0) = buffer.getAs[Boolean](0) && input.getAs[Boolean](0)
}
def merge(buffer1: MutableAggregationBuffer, buffer2: Row): Unit = {
buffer1(0) = buffer1.getAs[Boolean](0) && buffer2.getAs[Boolean](0)
}
def evaluate(buffer: Row): Any = {
buffer(0)
}
}
现在,实例化我们的类,也可以将其注册为一个函数
val ba = new BoolAnd
spark.udf.register("booland", ba)
import org.apache.spark.sql.functions._
spark.range(1)
.selectExpr("explode(array(TRUE, TRUE, TRUE)) as t")
.selectExpr("explode(array(TRUE, FALSE, TRUE)) as f", "t")
.select(ba(col("t")), expr("booland(f)"))
.show()
结果: