如何将火花行(StructType)投射到scala案例类

Posted

技术标签:

【中文标题】如何将火花行(StructType)投射到scala案例类【英文标题】:how to cast a spark row(StructType) to scala case class 【发布时间】:2018-12-13 05:14:08 【问题描述】:

我试图在 scala 中编写一个 udf 函数并在我的 pyspark 工作中使用它。 我的数据框架构是

root
|-- vehicle_id: string
|-- driver_id: string
|-- StartDtLocal: timestamp
|-- EndDtLocal: timestamp
|-- trips: array
|    |-- element: struct
|    |    |-- week_start_dt_local: timestamp
|    |    |-- week_end_dt_local: timestamp
|    |    |-- start_dt_local: timestamp
|    |    |-- end_dt_local: timestamp
|    |    |-- StartDtLocal: timestamp
|    |    |-- EndDtLocal: timestamp
|    |    |-- vehicle_id: string
|    |    |-- duration_sec: float
|    |    |-- distance_km: float
|    |    |-- speed_distance_ratio: float
|    |    |-- speed_duration_ratio: float
|    |    |-- speed_event_distance_km: float
|    |    |-- speed_event_duration_sec: float
|-- trip_details: array
|    |-- element: struct
|    |    |-- event_start_dt_local: timestamp
|    |    |-- force: float
|    |    |-- speed: float
|    |    |-- sec_from_start: float
|    |    |-- sec_from_end: float
|    |    |-- StartDtLocal: timestamp
|    |    |-- EndDtLocal: timestamp
|    |    |-- vehicle_id: string
|    |    |-- trip_duration_sec: float

我正在尝试编写一个 udf 函数

def calculateVariables(row: Row):HashMap[String, Float] = 
    case class myRow(week_start_dt_local: Timestamp, week_end_dt_local: Timestamp, start_dt_local: Timestamp, end_dt_local :Timestamp, StartDtLocal:Timestamp,EndDtLocal:Timestamp,vehicle_id:String,duration_sec:Int,distance_km:Int,speed_distance_ratio:Float,speed_duration_ratio:Float,speed_event_distance_km:Float,speed_event_duration_sec:Float)

val trips = row.getAs[WrappedArray[myRow]](4)

在此映射函数中,我试图将行转换为案例类,但无法。我收到此错误。

java.lang.ClassCastException:org.apache.spark.sql.catalyst.expressions.GenericRowWithSchema 无法转换为 VariableCalculation.VariableCalculation$myRow$3

谁能帮我解决这个问题?

【问题讨论】:

【参考方案1】:

问题是Row 上的.as 只是进行类型转换,没有别的。 trips的内部类型其实是Row

所以row.getAs[WrappedArray[Row]]("trips") 会起作用。然后你可以map覆盖它并从Row构造myRow

您可以使用 Sparks Encoder 以某种方式自动执行此操作,但它们更适用于整个数据集。

您是否考虑过为整个架构制定一个案例类,然后只做dataframe.as[MyCaseClass]?这将使您可以正确访问整个嵌套结构

【讨论】:

谢谢我会测试一下,其实我是从python背景到scala的新手。 你能给我更多关于如何映射它的想法吗? 我假设WrappedArray[Row] 上有一个.map “为整个模式制定案例类”对我来说效果最好。轻松多了。

以上是关于如何将火花行(StructType)投射到scala案例类的主要内容,如果未能解决你的问题,请参考以下文章

如何将火花数据帧的“第一”行复制到另一个数据帧?为啥我的最小示例失败了?

如何将新列和相应的行特定值添加到火花数据帧?

自定义数据源的自动火花模式推断

如何获取火花行的 value_counts?

如何将对象投射到桌子上?

将 URL 投射到 Chromecast 时,如何向它播放音频?