我知道如何在SparkSQL中编写UDF:
def belowThreshold(power: Int): Boolean = {
return power < -40
}
sqlContext.udf.register("belowThreshold", belowThreshold _)
我可以做类似的事情来定义聚合函数吗?这是怎么做到的?
对于上下文,我想运行以下SQL查询:
val aggDF = sqlContext.sql("""SELECT span, belowThreshold(opticalReceivePower), timestamp
FROM ifDF
WHERE opticalReceivePower IS NOT null
GROUP BY span, timestamp
ORDER BY span""")
它应该会返回类似于
行(span1,false,T0)
我希望聚合函数告诉我,在由< code>span和< code>timestamp定义的组中,是否有任何< code>opticalReceivePower的值低于阈值。我需要把我的UDAF写得和我上面粘贴的UDF不同吗?
要在火花(3.0) Java 中定义和使用 UDF,请执行以下操作:
private static UDF1<Integer, Boolean> belowThreshold = (power) -> power < -40;
注册虚拟硬盘录像机:
SparkSession.builder()
.appName(appName)
.master(master)
.getOrCreate().udf().register("belowThreshold", belowThreshold, BooleanType);
使用UDF by SparkSQL:
spark.sql("SELECT belowThreshold('50')");
火花
Scala < code > UserDefinedAggregateFunction 已被弃用(SPARK-30423 Deprecate UserDefinedAggregateFunction),取而代之的是注册的< code >聚合器。
火花
矢量化udf(仅限Python):
from pyspark.sql.functions import pandas_udf
from pyspark.sql.functions import PandasUDFType
from pyspark.sql.types import *
import pandas as pd
df = sc.parallelize([
("a", 0), ("a", 1), ("b", 30), ("b", -50)
]).toDF(["group", "power"])
def below_threshold(threshold, group="group", power="power"):
@pandas_udf("struct<group: string, below_threshold: boolean>", PandasUDFType.GROUPED_MAP)
def below_threshold_(df):
df = pd.DataFrame(
df.groupby(group).apply(lambda x: (x[power] < threshold).any()))
df.reset_index(inplace=True, drop=False)
return df
return below_threshold_
用法示例:
df.groupBy("group").apply(below_threshold(-40)).show()
## +-----+---------------+
## |group|below_threshold|
## +-----+---------------+
## | b| true|
## | a| false|
## +-----+---------------+
另请参阅在PySpark中对GroupeData应用UDF(具有功能的python示例)
火花
可以在类型化的数据集
上使用聚合器
:
import org.apache.spark.sql.expressions.Aggregator
import org.apache.spark.sql.{Encoder, Encoders}
class BelowThreshold[I](f: I => Boolean) extends Aggregator[I, Boolean, Boolean]
with Serializable {
def zero = false
def reduce(acc: Boolean, x: I) = acc | f(x)
def merge(acc1: Boolean, acc2: Boolean) = acc1 | acc2
def finish(acc: Boolean) = acc
def bufferEncoder: Encoder[Boolean] = Encoders.scalaBoolean
def outputEncoder: Encoder[Boolean] = Encoders.scalaBoolean
}
val belowThreshold = new BelowThreshold[(String, Int)](_._2 < - 40).toColumn
df.as[(String, Int)].groupByKey(_._1).agg(belowThreshold)
火花
在 Spark 1.5 中,您可以像这样创建 UDAF,尽管它很可能是矫枉过正:
import org.apache.spark.sql.expressions._
import org.apache.spark.sql.types._
import org.apache.spark.sql.Row
object belowThreshold extends UserDefinedAggregateFunction {
// Schema you get as an input
def inputSchema = new StructType().add("power", IntegerType)
// Schema of the row which is used for aggregation
def bufferSchema = new StructType().add("ind", BooleanType)
// Returned type
def dataType = BooleanType
// Self-explaining
def deterministic = true
// zero value
def initialize(buffer: MutableAggregationBuffer) = buffer.update(0, false)
// Similar to seqOp in aggregate
def update(buffer: MutableAggregationBuffer, input: Row) = {
if (!input.isNullAt(0))
buffer.update(0, buffer.getBoolean(0) | input.getInt(0) < -40)
}
// Similar to combOp in aggregate
def merge(buffer1: MutableAggregationBuffer, buffer2: Row) = {
buffer1.update(0, buffer1.getBoolean(0) | buffer2.getBoolean(0))
}
// Called on exit to get return value
def evaluate(buffer: Row) = buffer.getBoolean(0)
}
用法示例:
df
.groupBy($"group")
.agg(belowThreshold($"power").alias("belowThreshold"))
.show
// +-----+--------------+
// |group|belowThreshold|
// +-----+--------------+
// | a| false|
// | b| true|
// +-----+--------------+
火花 1.4 解决方法:
我不确定我是否正确理解了您的需求,但据我所知,这里简单的旧聚合应该足够了:
val df = sc.parallelize(Seq(
("a", 0), ("a", 1), ("b", 30), ("b", -50))).toDF("group", "power")
df
.withColumn("belowThreshold", ($"power".lt(-40)).cast(IntegerType))
.groupBy($"group")
.agg(sum($"belowThreshold").notEqual(0).alias("belowThreshold"))
.show
// +-----+--------------+
// |group|belowThreshold|
// +-----+--------------+
// | a| false|
// | b| true|
// +-----+--------------+
火花
据我所知,目前(Spark 1.4.1),除了Hive之外,没有对UDAF的支持。Spark 1.5应该可以(参见SPARK-3947)。
在内部,Spark 使用许多类,包括命令性聚合
和声明性聚合
。
有用于内部使用,可能会更改,恕不另行通知,所以它可能不是您想在生产代码中使用的东西,但只是为了完整性BelowThreshold
withDeclarativeAggregate
可以这样实现(使用Spark 2.2-SNAPSHOT测试):
import org.apache.spark.sql.catalyst.expressions.aggregate.DeclarativeAggregate
import org.apache.spark.sql.catalyst.expressions._
import org.apache.spark.sql.types._
case class BelowThreshold(child: Expression, threshold: Expression)
extends DeclarativeAggregate {
override def children: Seq[Expression] = Seq(child, threshold)
override def nullable: Boolean = false
override def dataType: DataType = BooleanType
private lazy val belowThreshold = AttributeReference(
"belowThreshold", BooleanType, nullable = false
)()
// Used to derive schema
override lazy val aggBufferAttributes = belowThreshold :: Nil
override lazy val initialValues = Seq(
Literal(false)
)
override lazy val updateExpressions = Seq(Or(
belowThreshold,
If(IsNull(child), Literal(false), LessThan(child, threshold))
))
override lazy val mergeExpressions = Seq(
Or(belowThreshold.left, belowThreshold.right)
)
override lazy val evaluateExpression = belowThreshold
override def defaultResult: Option[Literal] = Option(Literal(false))
}
应该用等效的< code > withAggregateFunction 进一步包装它。
我正在测试Cassandra中的UDF/UDA特性,看起来不错。但我在使用它时没有什么问题。 1) 在卡桑德拉。yaml,有人提到启用沙箱是为了避免邪恶代码,那么我们是否违反了规则,启用此支持(标志)会产生什么后果? 2)与在客户端读取数据和编写聚合逻辑相比,在Cassandra中使用UDF/UDA有什么优势? 3)此外,除了JAVA之外,是否有一种语言支持可用于编写UDF/UDA的nodejs、
问题内容: 我在数据库中创建了标量函数 现在,我想在.NET C#或VB.NET代码中运行它。 我使用实体框架,尝试使用功能映射对其进行映射,但未成功。我不在乎用简单的DbCommand来做到这一点,问题是我没有得到任何结果(该函数存在于Entities类中): 有什么解决办法吗?欢迎使用C#或VB.NET发布。 问题答案: 在这种情况下,听起来 正确的 方法是使用实体框架的功能来定义.NET
问题内容: 我正在尝试在Oracle中编写一个自定义聚合函数,并将该函数与其他一些函数一起分组在一个包中。作为一个示例(为了模拟我遇到的问题),假设我的自定义聚合对数字进行求和看起来像: 如果我编写以下函数定义: 和相应的类型声明进行测试: 这个说法: 给出正确的结果70。但是,使用函数定义创建一个包: 并通过以下方式调用: 与爆炸 是否可以在包声明中嵌套自定义聚合函数? 问题答案: Oracle
我想在UDAF中传递一个数组作为输入模式。 我给出的例子非常简单,它只是对2个向量求和。实际上我的用例更复杂,我需要使用UDAF。 在“显示”动作之前,所有这些都可以很好地进行转换。但这部剧引发了一个错误: 斯卡拉。MatchError:[WrappedArray(21.4,24.9,22.0)](属于org.apache.spark.sql.execution.aggregate.InputAg
我在我的cassandra db中实现了用户定义的聚合函数average,如链接https://docs.datastax.com/en/dse/5.1/cql/cql/cql_using/usecreateuda.html所述 创建或替换对空输入调用的函数avgState(state Tuple ,val int)返回元组 语言Java为“if(val!=NULL){state.SetInt(0
我正在研究MongoOperations的聚合函数,以便使用Spring数据进行某种中间层查询。正如aggregate()函数的文档中所定义的:http://docs.spring.io/spring-data/mongoDB/docs/current/api/org/springframework/data/mongoDB/core/mongooperations.html#aggregate-