Scala UDF 返回“不支持单元类型的架构”

Posted

技术标签:

【中文标题】Scala UDF 返回“不支持单元类型的架构”【英文标题】:Scala UDF returning 'Schema for type Unit is not supported' 【发布时间】:2018-07-02 15:55:45 【问题描述】:

我想更改数据框中的列。该列是整数数组。我想替换数组的一个元素,从另一个数组中获取索引并用第三个数组中的元素替换该元素。示例:我有三列 C1、C2、C3 所有三个数组。我想按如下方式替换 C3 中的元素。

C3[C2[i]] = C1[i].

我写了以下UDF:

def UpdateHist = udf((CRF_count: Seq[Long], Day: Seq[String], History: Seq[Int])=> for(i <- 0 to Day.length-1)History.updated(Day(i).toInt-1 , CRF_count(i).toInt))

并执行了这个:

histdate3.withColumn("History2", UpdateHist2(col("CRF_count"), col("Day"), col("History"))).show()

但它返回如下错误:

scala> histdate3.withColumn("History2", UpdateHist2(col("CRF_count"), col("Day"), col("History"))).show()

java.lang.UnsupportedOperationException:不支持 Unit 类型的架构 在 org.apache.spark.sql.catalyst.ScalaReflection$.schemaFor(ScalaReflection.scala:733) 在 org.apache.spark.sql.catalyst.ScalaReflection$.schemaFor(ScalaReflection.scala:671) 在 org.apache.spark.sql.functions$.udf(functions.scala:3100) 在 UpdateHist2(:25) ... 48 省略

我想我正在返回一些不同的类型,即不支持的 View 类型。请帮我解决这个问题。

【问题讨论】:

For 循环不返回任何内容,因此您使用的函数是 (Seq[Long], Seq[String], Seq[Int]) =&gt; Unit 是的。那我该如何更新数组呢?有没有其他办法? 【参考方案1】:

您的 for 循环返回 Unit 因此错误消息。你可以使用for-yield 来返回值,但是由于Seq 应该是updated,所以一个简单的foldLeft 会更好:

import org.apache.spark.sql.functions._

val df = Seq(
  (Seq(101L, 102L), Seq("1", "2"), Seq(11, 12)),
  (Seq(201L, 202L, 203L), Seq("2", "3"), Seq(21, 22, 23))
).toDF("C1", "C2", "C3")
// +---------------+------+------------+
// |C1             |C2    |C3          |
// +---------------+------+------------+
// |[101, 102]     |[1, 2]|[11, 12]    |
// |[201, 202, 203]|[2, 3]|[21, 22, 23]|
// +---------------+------+------------+

def updateC3 = udf( (c1: Seq[Long], c2: Seq[String], c3: Seq[Int]) =>
  c2.foldLeft( c3 ) (acc, i) =>
    val idx = i.toInt - 1
    acc.updated(idx, c1(idx).toInt)
  
)

df.withColumn("C3", updateC3($"C1", $"C2", $"C3")).show(false)
// +---------------+------+--------------+
// |C1             |C2    |C3            |
// +---------------+------+--------------+
// |[101, 102]     |[1, 2]|[101, 102]    |
// |[201, 202, 203]|[2, 3]|[21, 202, 203]|
// +---------------+------+--------------+

【讨论】:

太棒了!谢谢!

以上是关于Scala UDF 返回“不支持单元类型的架构”的主要内容,如果未能解决你的问题,请参考以下文章

Spark SQL UDF 使用 df.WithColumn() 返回 scala 不可变映射

Scala:可变参数 UDF

udf spark Scala 返回案例类

UDF scala 返回 [max,index]

rdd.mapPartitions 从 Spark Scala 中的 udf 返回布尔值

Scala UDF 函数对数组列进行操作并返回自定义值