Pyspark udf 对于没有参数的函数失败,但适用于没有参数的 lambda

Posted

技术标签:

【中文标题】Pyspark udf 对于没有参数的函数失败,但适用于没有参数的 lambda【英文标题】:Pyspark udf fails for a function with no arguments but works for a lambda with no arguments 【发布时间】:2019-04-23 22:07:55 【问题描述】:

我正在尝试使用 withColumn 和不带参数的 udf 向我的 Spark DataFrame 添加一列。这似乎只有在我使用 lambda 封装我的原始函数时才有效。

这是一个 MWE:

from pyspark.sql import Row, SparkSession
from pyspark.sql.functions import udf

spark = SparkSession.builder.getOrCreate()
df = spark.createDataFrame([Row(number=i) for i in range(10)])

def foo():
    return 'bar'

udfoo = udf(foo())
df = df.withColumn('word', udfoo())
# Fails with TypeError: _create_udf() missing 1 required positional argument: 'f'

udfoo = udf(lambda: foo())
df = df.withColumn('word', udfoo())
# Works

我已经设法实现了我想要的行为,所以“解决方案”并不是我想要的(尽管我欢迎任何关于更好/更惯用的方式来实现这种事情的建议)。如果有人在这里寻找“如何做”的答案,this other question might help。

我真正想要的是一个解释:为什么第一个解决方案会失败而第一个工作?

我在 Ubuntu 18.04.2 上使用 spark 2.4.0 和 python 3.7.3

【问题讨论】:

【参考方案1】:

udf 期望将一个函数传递给它,但是当您调用 foo() 时,它会立即计算为一个字符串。

如果您使用 udf(foo) 而不是 udf(foo()),您将看到预期的行为。

udfoo = udf(foo)
df = df.withColumn('word', udfoo())

如果有帮助,如果您正在尝试获取只是一个常量值的列,您可以使用pyspark.sql.functions.lit,例如:

from pyspark.sql import functions as F

df.withColumn('word', F.lit('bar'))

【讨论】:

这很有道理,这个问题一直困扰着我!感谢您对lit 的解释,这个 MWE 并不是我想要做的,但它可能会对未来的读者有所帮助。

以上是关于Pyspark udf 对于没有参数的函数失败,但适用于没有参数的 lambda的主要内容,如果未能解决你的问题,请参考以下文章

Pyspark SIZE 函数本身可以工作,但在 UDF 中它没有 [关闭]

PySpark UDF 无法识别参数数量

为啥运行 pandas_udf 时 Pyspark 失败?

Pyspark:使用带有参数的UDF创建一个新列[重复]

PySpark 用户定义函数 (UDF) 创建新列

在 PySpark Pandas UDF 中指定用户定义函数的正确方法