Spark Error:构造ClassDict的预期零参数(对于numpy.core.multiarray._reconstruct)

时间:2016-08-16 21:28:48

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

我在Spark中有一个数据框,其中一列包含一个数组。现在,我编写了一个单独的UDF,它将数组转换为另一个只有不同值的数组。见下面的例子:

Ex: [24,23,27,23] 应转换为 [24,23,27] 代码:

def uniq_array(col_array):
    x = np.unique(col_array)
    return x
uniq_array_udf = udf(uniq_array,ArrayType(IntegerType()))

Df3 = Df2.withColumn("age_array_unique",uniq_array_udf(Df2.age_array))

在上面的代码中,Df2.age_array是我在其上应用UDF以获取不同列"age_array_unique"的数组,该列应该只包含数组中的唯一值。

但是,只要我运行命令Df3.show(),我就会收到错误:

  

net.razorvine.pickle.PickleException:构造ClassDict的预期零参数(对于numpy.core.multiarray._reconstruct)

任何人都可以告诉我为什么会这样吗?

谢谢!

6 个答案:

答案 0 :(得分:31)

问题的根源是从UDF返回的对象不符合声明的类型。 np.unique不仅返回numpy.ndarray,还会使用NumPy API将数字转换为相应的DataFrame类型which are not compatible。你可以尝试这样的事情:

udf(lambda x: list(set(x)), ArrayType(IntegerType()))

或者这个(为了保持秩序)

udf(lambda xs: list(OrderedDict((x, None) for x in xs)), 
    ArrayType(IntegerType()))

代替。

如果你真的想要np.unique,你必须转换输出:

udf(lambda x: np.unique(x).tolist(), ArrayType(IntegerType()))

答案 1 :(得分:2)

您需要将最终值转换为python列表。您可以按以下方式实现该功能:

def uniq_array(col_array):
    x = np.unique(col_array)
    return list(x)

这是因为Spark无法理解numpy数组格式。为了提供Spark DataFrames理解为ArrayType的python对象,您需要在将输出返回之前将其转换为python list

答案 2 :(得分:0)

从pyspark 2.4版开始,您可以使用array_distinct转换。
http://spark.apache.org/docs/latest/api/python/pyspark.sql.html#pyspark.sql.functions.array_distinct

答案 3 :(得分:0)

当我的UDF返回一个float时,我也遇到了这个错误,但是我忘记将其强制转换为float。我需要这样做:

retval = 0.5
return float(retval)

答案 4 :(得分:0)

以下对我来说很好

udf(lambda x: np.unique(x).tolist(), ArrayType(IntegerType()))

答案 5 :(得分:0)

[x.item() for x in <any numpy array>]

将其转换为纯python。