Scala Spark—当我从映射调用自定义函数时,会得到一个java.lang.UnsupportedOperationException
我有一个数据帧,其结构类似于:Scala Spark—当我从映射调用自定义函数时,会得到一个java.lang.UnsupportedOperationException,scala,apache-spark,spark-dataframe,Scala,Apache Spark,Spark Dataframe,我有一个数据帧,其结构类似于: root |-- NPAData: struct (nullable = true) | |-- NPADetails: struct (nullable = true) | | |-- location: string (nullable = true) | | |-- manager: string (nullable = true) | |-- service: array (nullable = true)
root
|-- NPAData: struct (nullable = true)
| |-- NPADetails: struct (nullable = true)
| | |-- location: string (nullable = true)
| | |-- manager: string (nullable = true)
| |-- service: array (nullable = true)
| | |-- element: struct (containsNull = true)
| | | |-- serviceName: string (nullable = true)
| | | |-- serviceCode: string (nullable = true)
|-- NPAHeader: struct (nullable = true)
| | |-- npaNumber: string (nullable = true)
| | |-- date: string (nullable = true)
我想做的是:
- 将具有相同编号的记录分组到列表中
- 在每个列表中,根据元素的
日期对元素进行排序
- 一旦我对元素进行了分组和排序,我需要合并 应用一些逻辑的元素。要执行此列表步骤,我决定 使用地图
val toUpdate = sourceDF.withColumn("count", count($"NPAHeader").over(Window.partitionBy("NPAHeader.npaNumber").orderBy($"NPAHeader.date".desc))).filter($"count" > 1)
val groupedNpa = toUpdate.groupBy($"NPAHeader.npaNumber" ).agg(collect_list(struct($"NPAData",$"NPAHeader")).as("npa"))
//This is a simply version of my logic.
def pickOne(List: Seq[Row]): Row = {
println("First element: "+List.get(0))
List.get(0)
}
val mergedNpa = groupedNpa.map(row => (row.getAs[String]("npaNumber"),pickOne(row.getAs[Seq[Row]]("npa"))))
groupBy后面的行示例如下:
[1234,WrappedArray([npaNew,npaOlder,…npaOlder])]
但是当我试图从映射中调用函数时,我遇到了一个异常
线程“main”java.lang.UnsupportedOperationException中出现异常:否
找到org.apache.spark.sql.Row的编码器
-字段(类:“org.apache.spark.sql.Row”,名称:“_2”)
-根类:“scala.Tuple2”
我的理解是,我无法从映射中调用函数pickOne()
(或者至少不能以我尝试的方式调用)。但我不知道我做错了什么
为什么我会有这样的例外
谢谢你的时间
注意:我知道有更简单的方法可以从列表中选择一个元素,而无需调用自定义函数。但我需要调用yes或yes,因为在下一步中,我需要在那里放置一个更复杂的逻辑来合并行
使用Mahesh Chand Kandpal建议后:
import org.apache.spark.sql.catalyst.encoders.RowEncoder
grouped.map(row => "emdNumber: "+row.getAs[String]("emdNumber"))
val mergedNpa = groupedNpa.map(row => (row.getAs[String]("npaNumber"),pickOne(row.getAs[Seq[Row]]("npa"))(RowEncoder(row.schema))))
我得到以下错误:
类型失配;发现:
org.apache.spark.sql.catalyst.encoders.ExpressionEncoder[org.apache.spark.sql.Row]
必填项:Int
我应该如何应用编码器呢?当您将map与数据帧一起使用时,需要指定编码器 在spark 2.x
Dataset[Row]中,映射为((Row)⇒ T) (编码器[T])⇒ 数据集[T]
import org.apache.spark.sql.catalyst.encoders.RowEncoder
implicit val encoder = RowEncoder(schema)
谢谢你的回答,但是出现了一个新的错误,请检查编辑。我认为你应该在地图之外的groupedNpa上提供编码器。implicit val encoder=RowEncoder(模式)给出数据帧的模式。同样的结果,我应该如何传递映射?如果可以显示groupedNpa。我可以试试我的贝壳。这是一个玩具的例子。我拥有的真正的一个要复杂得多。但是,您能否在回答中添加一行代码,说明如何使用编码器调用自定义函数?