java.lang.ClassCastException: org.apache.spark.sql.catalyst.expressions.GenericRowWithSchema cannot

先准备构造一个DataFrame,其中scores字段是一个序列,里面的每一个元素是一个元组:

import spark.implicits._

val df: DataFrame = Seq(
  ("A", Seq(("1", 5.0), ("3", 2.0))),
  ("B", Seq(("1", 4.0), ("2", 5.0))),
  ("C", Seq(("2", 5.0), ("3", 2.0)))
).toDF("userId", "scores")
  .cache()

df.printSchema()
df.show(false)

可以看到这个DataFrame的scores字段是ArrayType,而里面的每一个元素是StructType

root
 |-- userId: string (nullable = true)
 |-- scores: array (nullable = true)
 |    |-- element: struct (containsNull = true)
 |    |    |-- _1: string (nullable = true)
 |    |    |-- _2: double (nullable = false)
+------+------------------+
|userId|scores            |
+------+------------------+
|A     |[[1,5.0], [3,2.0]]|
|B     |[[1,4.0], [2,5.0]]|
|C     |[[2,5.0], [3,2.0]]|
+------+------------------+

需求:构建一个UDF函数作用于这个DataFrame的scores字段,以便计算每一条scores的模:

    // 计算向量的模
    val vecLen: UserDefinedFunction = udf { vector: Seq[(String, Double)] =>
      var length = 0.0
      for (score <- vector) {
        length += (score._2 * score._2)
      }
      Math.sqrt(length)
    }

    df.withColumn("vecLen", vecLen($"scores")).show()

此时报错:
java.lang.ClassCastException: org.apache.spark.sql.catalyst.expressions.GenericRowWithSchema cannot be cast to scala.Tuple2
Spark认为scores中的每一个元素是GenericRowWithSchema类型的,不能转换成Tuple2
事实上,scores中的每个元素是Struct类型的,如果想要取出来,它是一个Row类型的。
据了解,像StringSeq[Double] 这种类型就可以直接取出来,但是像 Seq[(Double,Double)] 这种类型直接取的话就会丢失schema信息,Spark认为(Double,Double)Row类型的。
可以这样更改UDF函数:

// 计算向量的模
val vecLen: UserDefinedFunction = udf { vector: Seq[Row] =>
  var length = 0.0
  for (score <- vector) {
    length += (score.getDouble(1) * score.getDouble(1))
  }
  Math.sqrt(length)
}

df.withColumn("vecLen", vecLen($"scores")).show()

这样就能得到正确的结果:

+------+------------------+------------------+
|userId|            scores|            vecLen|
+------+------------------+------------------+
|     A|[[1,5.0], [3,2.0]]| 5.385164807134504|
|     B|[[1,4.0], [2,5.0]]|6.4031242374328485|
|     C|[[2,5.0], [3,2.0]]| 5.385164807134504|
+------+------------------+------------------+
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值