是否可以将字符串注册为 UDF?

Posted

技术标签:

【中文标题】是否可以将字符串注册为 UDF?【英文标题】:Is it possible to register a string as a UDF? 【发布时间】:2020-08-01 04:26:30 【问题描述】:

在 Spark (Scala) 中,应用程序 jar 提交到 Spark 后,jar 是否可以从数据库表中获取许多字符串,将每个字符串转换为催化剂表达式,然后将该表达式转换为 UDF,以及使用UDF过滤另一个DataFrame中的行,最后将每个UDF的结果联合起来?

(上述表达式需要DataFrame的部分或全部列,但需要哪些列在jar的代码编写时是未知的,DataFrame的架构在开发时是已知的)

一个例子:

表达式1:"id == 1"

表达式 2:"name == \"andy\""

数据帧:

第 1 行:id = 1,name = "red",age = null 第 2 行:id = 2,name = "andy",age = 20 第 3 行:id = 3,name = "juliet",age = 21

最终结果应该是前两行

注意:首先将两个表达式与or 连接是不可接受的,因为我需要跟踪哪个表达式导致结果行

【问题讨论】:

【参考方案1】:

已编辑:过滤每个参数并合并所有。

import org.apache.spark.sql.DataFrame

val df = spark.read.option("header","true").option("inferSchema","true").csv("test1.csv")

val args = Array("id == 1", "name == \"andy\"")
val filters = args.zipWithIndex

var dfs = Array[DataFrame]()

filters.foreach 
    case (filter, index) => 
        val tempDf = df.filter(filter).withColumn("index", lit(index))
        dfs = dfs :+ tempDf


val resultDF = dfs.reduce(_ unionAll _)
resultDF.show(false)

+---+----+----+-----+
|id |name|age |index|
+---+----+----+-----+
|1  |red |null|0    |
|2  |andy|20  |1    |
+---+----+----+-----+

原文:为什么只是把字符串放到过滤器中?

val df = spark.read.option("header","true").option("inferSchema","true").csv("test.csv")

val condition = "id == 1 or name == \"andy\""
df.filter(condition).show(false)

+---+----+----+
|id |name|age |
+---+----+----+
|1  |red |null|
|2  |andy|20  |
+---+----+----+

我错过了什么?

【讨论】:

我应该提到的是,在一个jar中要执行多个(开发时数量未知)表达式,最终结果是每个表达式的结果的并集。我已经更新了这个问题。谢谢:)

以上是关于是否可以将字符串注册为 UDF?的主要内容,如果未能解决你的问题,请参考以下文章

是否可以在 Excel UDF 中使用反斜杠 `\` 字符?

ExcelDNA 在运行时动态注册 UDF

将 kmeans 模型注册为 UDF

如何将此字符串拆分为 UDF

PySpark UDF 无法识别参数数量

错误 1075:从 UDF 接收到一个字节数组。无法确定如何将字节数组转换为字符串