具有多个参数的 PySpark UDF 返回 null

Posted

技术标签:

【中文标题】具有多个参数的 PySpark UDF 返回 null【英文标题】:PySpark UDF with multiple arguments returns null 【发布时间】:2018-09-26 04:04:41 【问题描述】:

我有一个 PySpark 数据框,它有两列(AB,其类型为double),其值为0.01.0。 我正在尝试添加一个新列,这是这两者的总和。 我遵循了Pyspark: Pass multiple columns in UDF中的示例

import pyspark.sql.functions as F
from pyspark.sql.types import IntegerType, StringType
sum_cols = F.udf(lambda x: x[0]+x[1], IntegerType())
df_with_sum = df.withColumn('SUM_COL',sum_cols(F.array('A','B')))
df_with_sum.select(['SUM_COL']).toPandas()

这显示了一系列NULLs,而不是我预期的结果。

我尝试了以下任何方法来查看数据类型是否存在问题

sum_cols = F.udf(lambda x: x[0], IntegerType())
sum_cols = F.udf(lambda x: int(x[0]), IntegerType())

仍然得到空值。

我尝试删除数组:

sum_cols = F.udf(lambda x: x, IntegerType())
df_with_sum = df.withColumn('SUM_COL',sum_cols(df.A))

这工作正常并显示0/1

我尝试删除 UDF,但保留了数组:

df_with_sum = df.withColumn('SUM_COL', F.array('A','B'))

这很好用,并显示了一系列[0.0/1.0, 0.0/1.0] 的数组

所以,数组工作正常,UDF 工作正常,只是当我尝试将数组传递给 UDF 时,事情就崩溃了。我做错了什么?

【问题讨论】:

A列和B列的数据类型是什么?你能检查一下并更新问题吗? @RameshMaharjan 是的,更新了!类型为 double。 0/1 怎么加倍?是 0/1 还是 0.1? @RameshMaharjan 对于 A 和 B,它是 0.0 或 1.0,输出应该是 0、1 或 2(取决于操作是什么,我展示了几个示例 - 其中一个我称之为 int( ) 在 UDF 中,UDF 返回的是 IntegerType,在另一个我根本不使用 UDF,所以它是 0.0 或 1.0) 我不理解 0.0/1.0 的形式,如果数据类型是双精度,它应该是 0.0。如果值为0.0/1.0,则数据类型应为StringType。不是吗? 【参考方案1】:

问题是你试图在一个应该输出一个整数的函数中返回一个 double,它不适合,并且 pyspark 默认情况下在强制转换失败时默默地求助于NULL

df_with_doubles = spark.createDataFrame([(1.0,1.0), (2.0,2.0)], ['A', 'B'])
sum_cols = F.udf(lambda x: x[0]+x[1], IntegerType())
df_with_sum = df_with_double.withColumn('SUM_COL',sum_cols(F.array('A','B')))
df_with_sum.select(['SUM_COL']).toPandas()

你得到:

  SUM_COL
0    None
1    None

但是,如果你这样做:

df_with_integers = spark.createDataFrame([(1,1), (2,2)], ['A', 'B'])
sum_cols = F.udf(lambda x: x[0]+x[1], IntegerType())
df_with_sum = df_with_integers.withColumn('SUM_COL',sum_cols(F.array('A','B')))
df_with_sum.select(['SUM_COL']).toPandas()

你得到:

   SUM_COL
0        2
1        4

因此,要么预先将列转换为 IntegerType(或将它们转换为 UDF),要么将 UDF 的返回类型更改为 DoubleType

【讨论】:

以上是关于具有多个参数的 PySpark UDF 返回 null的主要内容,如果未能解决你的问题,请参考以下文章

PySpark UDF 无法识别参数数量

在 for 循环中使用 udf 在 Pyspark 中创建多个列

如何在 Pyspark 中使用 @pandas_udf 返回多个数据帧?

如何在 PySpark 中将多个参数传递给 Pandas UDF?

如何使用具有多个源列的 pandas_udf 将多个列添加到 pyspark DF?

如何在 Pyspark UDF 中返回双精度列表?