具有多个参数的 PySpark UDF 返回 null
Posted
技术标签:
【中文标题】具有多个参数的 PySpark UDF 返回 null【英文标题】:PySpark UDF with multiple arguments returns null 【发布时间】:2018-09-26 04:04:41 【问题描述】:我有一个 PySpark 数据框,它有两列(A
、B
,其类型为double
),其值为0.0
或1.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()
这显示了一系列NULL
s,而不是我预期的结果。
我尝试了以下任何方法来查看数据类型是否存在问题
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的主要内容,如果未能解决你的问题,请参考以下文章
在 for 循环中使用 udf 在 Pyspark 中创建多个列
如何在 Pyspark 中使用 @pandas_udf 返回多个数据帧?
如何在 PySpark 中将多个参数传递给 Pandas UDF?