Spark - 当我从地图

时间:2017-09-28 08:00:32

标签: scala apache-spark spark-dataframe

我有一个DataFrame,其结构类似于:

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)

我的目的是:

  • 将具有相同npaNumber的记录分组到列表中
  • 在每个列表中,根据date
  • 对元素进行排序
  • 一旦我将元素分组并排序,我需要合并 元素应用一些逻辑。为了执行此列表步骤,我决定 使用地图。

这是我到目前为止所尝试的内容:

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,... npaOldest])]

但是当我尝试从地图调用该函数时,我收到了异常。

  

线程中的异常" main" java.lang.UnsupportedOperationException:没有   找到org.apache.spark.sql.Row的编码器    - field(class:" org.apache.spark.sql.Row",name:" _2")    - root class:" scala.Tuple2"

我理解的是我不能从地图中调用函数pickOne()(或者至少不是我尝试它的方式)。但我不知道自己做错了什么。

为什么我有这个例外?

谢谢你的时间!

注意:我知道有更简单的方法可以从列表中选取一个元素而无需调用自定义函数。但我需要调用它是或是,因为在下一步中我需要放置一个更复杂的逻辑来合并行。

使用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

我应该如何应用编码器?

1 个答案:

答案 0 :(得分:1)

当您使用带数据框架的地图时,您需要提供编码器。

在spark 2.x Dataset[Row].map is ((Row) ⇒ T)(Encoder[T]) ⇒ Dataset[T]

import org.apache.spark.sql.catalyst.encoders.RowEncoder
implicit val encoder = RowEncoder(schema)