You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Scala Spark代码报错Unsupported literal type DenseVector 求助

问题解决:Spark中DenseVector无法作为字面量替换空值的错误

错误原因

Spark的lit()函数仅支持基本数据类型(如Int、String、Double),不直接支持org.apache.spark.ml.linalg.DenseVector这类MLlib复杂类型。即使移除lit(),直接将本地的DenseVector对象传入when分支,Spark仍会尝试将其解析为字面量,同样触发不支持类型的错误。

解决方案

方法1:使用typedLit()(Spark 2.2+推荐)

typedLit()是Spark专门为复杂类型(向量、数组、自定义类等)设计的字面量构造函数,直接替换原代码中的lit()即可:

import org.apache.spark.sql.functions.typedLit
import org.apache.spark.ml.linalg.DenseVector

val joinedDf = sampleDf
  .join(
    normalizedParentEmbedding.select(col("parent_product"), col("normalized_vector").as("parent_vector")),
    Seq("parent_product"),
    "left"
  )
  .join(
    normalizedChildEmbeddingDf.select(col("child_product"), col("normalized_vector").alias("child_vector")),
    Seq("child_product"),
    "left"
  )
  .withColumn("parent_vector", when(col("parent_vector").isNull,
         typedLit(normalizedDefaultParentEmbeddingDf.select("parent_vector").head()(0).asInstanceOf[DenseVector]))
         .otherwise(col("parent_vector")))
  .withColumn("child_vector", when(col("child_vector").isNull,                
         typedLit(normalizedDefaultChildEmbeddingDf.select("child_vector").head()(0).asInstanceOf[DenseVector]))
         .otherwise(col("child_vector")))

方法2:通过广播单行DataFrame引入默认值(兼容低版本Spark)

如果你的Spark版本低于2.2,可先将默认向量封装为单行DataFrame,通过广播关联后用coalesce替换空值:

import org.apache.spark.ml.linalg.DenseVector
import org.apache.spark.sql.functions.{broadcast, coalesce}

// 获取默认向量并创建单行DataFrame
val defaultParentVec = normalizedDefaultParentEmbeddingDf.select("parent_vector").head()(0).asInstanceOf[DenseVector]
val defaultParentDf = spark.createDataFrame(Seq(defaultParentVec)).toDF("default_parent_vec")

val defaultChildVec = normalizedDefaultChildEmbeddingDf.select("child_vector").head()(0).asInstanceOf[DenseVector]
val defaultChildDf = spark.createDataFrame(Seq(defaultChildVec)).toDF("default_child_vec")

// 执行关联与空值替换
val joinedDf = sampleDf
  .join(
    normalizedParentEmbedding.select(col("parent_product"), col("normalized_vector").as("parent_vector")),
    Seq("parent_product"),
    "left"
  )
  .join(
    normalizedChildEmbeddingDf.select(col("child_product"), col("normalized_vector").alias("child_vector")),
    Seq("child_product"),
    "left"
  )
  .crossJoin(broadcast(defaultParentDf))
  .crossJoin(broadcast(defaultChildDf))
  .withColumn("parent_vector", coalesce(col("parent_vector"), col("default_parent_vec")))
  .withColumn("child_vector", coalesce(col("child_vector"), col("default_child_vec")))
  .drop("default_parent_vec", "default_child_vec")

关键说明

  • typedLit()会保留复杂类型的结构信息,让Spark正确识别DenseVector类型
  • 广播单行DataFrame避免全量数据的笛卡尔积开销,保证性能

内容的提问来源于stack exchange,提问作者Munichong

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 17:24:50