【问题标题】:Writing a Pyspark UDF that functions like the Python any function编写一个 Pyspark UDF,其功能类似于 Python any 函数
【发布时间】:2017-09-17 13:52:10
【问题描述】:

我想编写一个 any_lambda 函数来检查 ArrayType 列中的任何元素是否满足 lambda 函数指定的条件。

这是我的代码不起作用:

def any_lambda(f, l):
    return any(list(map(f, l)))

spark.udf.register("any_lambda", any_lambda)

source_df = spark.createDataFrame(
    [
        ("jose", [1, 2, 3]),
        ("li", [4, 5, 6]),
        ("luisa", [10, 11, 12]),
    ],
    StructType([
        StructField("name", StringType(), True),
        StructField("nums", ArrayType(StringType(), True), True),
    ])
)

actual_df = source_df.withColumn(
    "any_num_greater_than_5",
    any_lambda(lambda n: n > 5, col("nums"))
)

此代码引发TypeError: Column is not iterable

如何创建一个有效的any_lambda 函数?

【问题讨论】:

    标签: apache-spark pyspark


    【解决方案1】:

    Udf 期望参数是列,lambda 函数不是列;您可能要做的是定义any_lambda,以便它接受一个lambda函数并返回一个udf

    import pyspark.sql.functions as F
    
    def any_lambda(f):
        @F.udf
        def temp_udf(l):
            return any(map(f, l))
        return temp_udf
    
    source_df = spark.createDataFrame(
        [
            ("jose", [1, 2, 3]),
            ("li", [4, 5, 6]),
            ("luisa", [10, 11, 12]),
        ],
        StructType([
            StructField("name", StringType(), True),
            StructField("nums", ArrayType(IntegerType(), True), True),
        ])
    )
    
    actual_df = source_df.withColumn(
        "any_num_greater_than_5",
        any_lambda(lambda n: n > 5)(col("nums"))
    )
    
    actual_df.show()
    +-----+------------+----------------------+
    | name|        nums|any_num_greater_than_5|
    +-----+------------+----------------------+
    | jose|   [1, 2, 3]|                 false|
    |   li|   [4, 5, 6]|                  true|
    |luisa|[10, 11, 12]|                  true|
    +-----+------------+----------------------+
    

    或者正如@Powers 所说,要明确返回的列类型,我们可以在udf 中指定返回的类型,如下所示:

    def any_lambda(f):
        def temp_udf(l):
            return any(map(f, l))
        return F.udf(temp_udf, BooleanType())
    

    现在架构看起来像:

    actual_df.printSchema()
    root
     |-- name: string (nullable = true)
     |-- nums: array (nullable = true)
     |    |-- element: integer (containsNull = true)
     |-- any_num_greater_than_5: boolean (nullable = true)
    

    【讨论】:

    • 很棒的答案。我删除了@F.udf 并添加了return F.udf(temp_udf, BooleanType()) 以使any_num_greater_than_5 成为布尔列。在您的回答中,它是一个字符串列。您能否更新您的答案以显示这两个选项?
    • @Powers 好电话。编辑答案以反映这一点。
    • 嗨,Psidom,你能告诉我这条线是如何工作的............ any_lambda(lambda n: n > 5)(col("nums"))
    猜你喜欢
    • 1970-01-01
    • 2019-09-05
    • 1970-01-01
    • 1970-01-01
    • 2017-05-21
    • 2010-12-13
    • 1970-01-01
    • 2017-03-15
    • 2014-09-08
    相关资源
    最近更新 更多