将 PySpark DenseVector 转换为数组

erw*_*nlc 4 python pyspark

我正在尝试将 DenseVector 的 pyspark 数据帧列转换为数组,但我总是遇到错误。

data = [(Vectors.dense([8.0, 1.0, 3.0, 2.0, 5.0]),),
(Vectors.dense([2.0, 0.0, 3.0, 4.0, 5.0]),),
(Vectors.dense([4.0, 0.0, 0.0, 6.0, 7.0]),)]

df = spark.createDataFrame(data,["features"])
Run Code Online (Sandbox Code Playgroud)

我试图定义一个 UDF 并使用 toArray()

to_array = udf(lambda x: x.toArray(), ArrayType(FloatType()))
df = df.withColumn('features', to_array('features'))
Run Code Online (Sandbox Code Playgroud)

但是,如果我执行 df.collect(),我会收到以下错误

org.apache.spark.SparkException: Job aborted due to stage failure: Task 1 in stage 17.0 failed 4 times, 
most recent failure: Lost task 1.3 in stage 17.0 (TID 100, 10.139.64.6, executor 0): 
net.razorvine.pickle.PickleException: expected zero arguments for construction of ClassDict 
(for numpy.core.multiarray._reconstruct)
Run Code Online (Sandbox Code Playgroud)

关于如何实现这一目标的任何想法?

cro*_*oik 9

toArray()返回一个不能ArrayType(FloatType())隐式转换的 numpy.ndarray 。另外使用.tolist()来转换它:

import pyspark.sql.functions as F
import pyspark.sql.types as T

#or: to_array = F.udf(lambda v: list([float(x) for x in v]), T.ArrayType(T.FloatType()))
to_array = F.udf(lambda v: v.toArray().tolist(), T.ArrayType(T.FloatType()))
df = df.withColumn('features', to_array('features'))
Run Code Online (Sandbox Code Playgroud)

如果您使用的是 Pyspark >=3.0.0,您可以使用新的vector_to_array函数:

from pyspark.ml.functions import vector_to_array
df = df.withColumn('features', vector_to_array('features'))
Run Code Online (Sandbox Code Playgroud)

  • 这个答案也许让我免于从阳台上跳下去。 (4认同)
  • 如果您使用的是 Spark 3.0.0,那么可以使用一个有趣的方法来执行此操作:vector_to_array。有关更多信息,请参阅此[答案](/sf/answers/2686952341/)。 (2认同)