如何使用变换高阶函数?

Posted

技术标签:

【中文标题】如何使用变换高阶函数?【英文标题】:How to use transform higher-order function? 【发布时间】:2018-12-13 12:12:34 【问题描述】:

关于transform高阶函数(https://issues.apache.org/jira/browse/SPARK-23908)。

有没有办法将它用作标准功能(在包org.apache.spark.sql.functions._中)?

我有一个字符串数组,我想对每个字符串应用 URI 规范化。现在我用 UDF 做到了。我刚刚使用 spark 2.4.0 跳过了 UDF。

正如我所见,它应该在 selectExpr 中使用,例如 df.selectExpr("transform(i, x -> x + 1)"),但它是否仅适用于 selectExpr

以这种方式使用它是否可以为转换提供自定义功能?有什么方法可以实现它,还是我应该求助于使用好的旧 UDF?

【问题讨论】:

您能描述一下您的用例吗?我认为使用 UDF 在性能方面是最快的。 我有一个字符串数组,我想对每个字符串应用 URI 规范化。现在我用 UDF 做到了。我刚刚使用 spark 2.4.0 跳过了 UDF。 【参考方案1】:

是否可以将其用作位于包 org.apache.spark.sql.functions._ 中的标准函数?

目前它仅用于 SQL 表达式,但如果您想返回 Column,请使用 expr

org.apache.spark.sql.functions._

expr("transform(i, x -> x + 1)"): Column

以这种方式使用它是否可以为转换提供自定义功能?

可以使用 Scala UDF*:

spark.udf.register("f", (x: Int) => x + 1)

Seq((1, Seq(1, 2, 3))).toDF("id", "xs")
  .withColumn("xsinc", expr("transform(xs, x -> f(x))"))
  .show
+---+---------+---------+
| id|       xs|    xsinc|
+---+---------+---------+
|  1|[1, 2, 3]|[2, 3, 4]|
+---+---------+---------+

虽然它似乎并没有比采用 Seq 的 UDF 提供任何真正的好处。


* 对 Python UDF 的部分支持似乎已经到位(udf 被识别,类型被正确派生,调用被分派),但是从 2.4.0 开始,序列化机制似乎被破坏了(所有记录都是作为None传递给UDF):

from typing import Optional
from pyspark.sql.functions import expr

sc.version
'2.4.0'
def f(x: Optional[int]) -> Optional[int]:
    return x + 1 if x is not None else None

spark.udf.register('f', f, "integer")

df = (spark
    .createDataFrame([(1, [1, 2, 3])], ("id", "xs"))
    .withColumn("xsinc", expr("transform(xs, x -> f(x))")))

df.printSchema()
root
 |-- id: long (nullable = true)
 |-- xs: array (nullable = true)
 |    |-- element: long (containsNull = true)
 |-- xsinc: array (nullable = true)
 |    |-- element: integer (containsNull = true)
df.show()
+---+---------+-----+
| id|       xs|xsinc|
+---+---------+-----+
|  1|[1, 2, 3]| [,,]|
+---+---------+-----+

当然,这里没有真正的性能提升潜力 - 它分派到 BasePythonRunner,因此开销应该与普通的 udf 相同。

相关JIRA票SPARK-27052 - Using PySpark udf in transform yields NULL values

【讨论】:

你说如果你想要一个 hof 返回一列使用 F.expr() 的事实让我认为在 SQL 中你可以使用它们来做更多的事情,而不仅仅是在单个列上工作。这可能吗?

以上是关于如何使用变换高阶函数?的主要内容,如果未能解决你的问题,请参考以下文章

Kotlin函数式编程 ① ( 函数式编程简介 | 高阶函数 | 函数类别 | Transform 变换函数 | 过滤函数 | 合并函数 | map 变换函数 | flatMap 变换函数 )

如何在 swift iOS 中使用 swift 高阶函数从本地 json 创建 ViewModel

如何理解高阶函数

使用 Context API 示例解释 React 高阶组件

Gen:如何将多个生成函数轨迹组合成一个高阶生成函数?

使用Context API示例解释的React高阶组件