PySpark UDF返回可变大小的元组

时间:2018-01-09 23:15:34

标签: python apache-spark pyspark apache-spark-sql user-defined-functions

我使用现有的Dataframe并使用包含元组的字段创建一个新的Dataframe。 UDF用于生成此字段。例如,在这里,我采用源元组并修改其元素以生成新元素:

udf( lambda x: tuple([2*e for e in x], ...)

挑战在于元组的长度是事先不知道的,并且可以在行之间变化。

从我理解阅读相关讨论,返回一个元组,UDF的返回类型必须声明为StructType。但是,由于返回的元组中的元素数量未知,我不能只写出类似的内容:

StructType([
    StructField("w1", IntegerType(), False),
    StructField("w2", IntegerType(), False),
    StructField("w3", IntegerType(), False)])

似乎可以返回列表,但列表对我来说不起作用,因为我需要在输出Dataframe中有一个可散列对象。

我有什么选择?

提前致谢

2 个答案:

答案 0 :(得分:2)

StructType / Row表示固定大小的product type对象,不能用于表示可变大小的对象。

要表示同类集合,请使用list作为外部类型,并使用ArrayType作为SQL类型:

udf(lambda x: [2*e for e in x], ArrayType(IntegerType()))

或(Spark 2.2或更高版本):

udf(lambda x: [2*e for e in x], "array<integer>")

在Spark 2.4或更高版本中,您可以使用transform

from pyspark.sql.functions import expr

expr("tranform(input_column, x -> 2 * x)")

答案 1 :(得分:0)

每个Databricks(Spark)的新语法一次排成一行(与Pandas UDF一致,这似乎是udfs在python https://databricks.com/blog/2017/10/30/introducing-vectorized-udfs-for-pyspark.html中的作用):

一次一行:

@udf(ArrayType(IntegerType()))
def new_tuple(x):
    return [2*e for e in x]