【问题标题】:Using a pyspark sql function inside lambda causing pickle error在 lambda 中使用 pyspark sql 函数导致 pickle 错误
【发布时间】:2021-10-10 04:20:53
【问题描述】:

我有一个如下图所示的pyspark代码:

if has_column(df_s_a, "x"):
    df6 = df_s_a \
        .withColumn("x", explode_outer(f.col("x"))) \
        .withColumn("y", 
                    f.udf(
                    lambda x: element_at("z.r.id", -1) if x=='C' else lit(None).cast("string"),
                        StringType()
                    )(col('x.type'))
                   ) \
            .select(
                from_unixtime(col("x.p")).alias("xp"),
                f.col("y"),
        )

我尝试在 lambda 内部对数据帧 d_s_a 进行任何访问,都会导致以下错误:

TypeError                                 Traceback (most recent call last)
/usr/local/lib/python3.9/site-packages/pyspark/serializers.py in dumps(self, obj)
    436         try:
--> 437             return cloudpickle.dumps(obj, pickle_protocol)
    438         except pickle.PickleError:
.
.
.
PicklingError: Could not serialize object: TypeError: cannot pickle '_thread.RLock' object

有没有一种方法可以在 lambda 中调用 SQL 函数?我也使用了 when() 子句,但它会评估 when & else 不管条件:Case when statement to conditionally populate columns in pyspark

【问题讨论】:

  • 你不能在 UDF 中使用任何 PySpark 函数,你也不能在 UDF 中访问数据框本身。如果您可以通过示例输入和预期输出稍微解释一下您的 UDF 函数,我想可能有一种方法可以在没有 UDF 的情况下做到这一点

标签: apache-spark pyspark apache-spark-sql


【解决方案1】:

您不能在 udf 中使用 Column 函数。 udf 从单行而不是整列中获取传递的元素。 因此,不要使用 lit(None),而是使用 None。 而不是 element_at("z.r.id", -1) 使用 id[-1] 将 z.r.id 传递给 udf。

【讨论】:

  • 我已经按照您的建议进行了尝试,这是修改后的 UDF:.withColumn("y", udf( lambda x : z.r.id[-1] if 'C' in x else None, StringType() )(col('x.type')) \ ) 我仍然遇到同样的错误。似乎,我无法在 if 条件下访问数据框。对数据框的任何引用都会导致此错误。有什么方法可以在 if 条件下进行引用并获取最后一个元素?
猜你喜欢
  • 1970-01-01
  • 2021-06-13
  • 1970-01-01
  • 2013-09-16
  • 2019-07-24
  • 2020-07-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多