Apache spark 编写一个Pyspark UDF,其功能与Python any函数类似

Apache spark 编写一个Pyspark UDF,其功能与Python any函数类似,apache-spark,pyspark,Apache Spark,Pyspark,我想编写一个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]),

我想编写一个
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"))
)
此代码引发
类型错误:列不可编辑


如何创建一个
任何可用的\u lambda
函数?

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)

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\u udf,BooleanType())
,以使
任何大于5的数值都成为布尔列。在您的答案中,它是一个字符串列。您能更新您的答案以显示两个选项吗?@Powers Good call。编辑答案以反映这一点。嗨,Psidom,你能告诉我这条线是如何工作的吗。。。。。。。。。任何lambda(lambda n:n>5)(col(“nums”))的回答都很棒。我删除了
@F.udf
并添加了
return F.udf(temp\u udf,BooleanType())
,以使
任何大于5的数值都成为布尔列。在您的答案中,它是一个字符串列。您能更新您的答案以显示两个选项吗?@Powers Good call。编辑答案以反映这一点。嗨,Psidom,你能告诉我这条线是如何工作的吗。。。。。。。。。任何λ(λn:n>5)(列(“nums”))