【发布时间】:2019-02-23 00:05:41
【问题描述】:
我有一个以下格式的 spark 数据框需要分解。我检查了其他解决方案,例如this one。但是,就我而言,before 和 after 可以是不同长度的数组。
root
|-- id: string (nullable = true)
|-- before: array (nullable = true)
| |-- element: struct (containsNull = true)
| | |-- start_time: string (nullable = true)
| | |-- end_time: string (nullable = true)
| | |-- area: string (nullable = true)
|-- after: array (nullable = true)
| |-- element: struct (containsNull = true)
| | |-- start_time: string (nullable = true)
| | |-- end_time: string (nullable = true)
| | |-- area: string (nullable = true)
例如,如果数据框只有一行,before 是一个大小为 2 的数组,after 是一个大小为 3 的数组,分解后的版本应该有 5 行,具有以下架构:
root
|-- id: string (nullable = true)
|-- type: string (nullable = true)
|-- start_time: integer (nullable = false)
|-- end_time: string (nullable = true)
|-- area: string (nullable = true)
其中type 是一个新列,可以是"before" 或“之后”。
我可以在两个单独的爆炸中执行此操作,我在每个爆炸中创建 type 列,然后在 union 中创建。
val dfSummary1 = df.withColumn("before_exp",
explode($"before")).withColumn("type",
lit("before")).withColumn(
"start_time", $"before_exp.start_time").withColumn(
"end_time", $"before_exp.end_time").withColumn(
"area", $"before_exp.area").drop("before_exp", "before")
val dfSummary2 = df.withColumn("after_exp",
explode($"after")).withColumn("type",
lit("after")).withColumn(
"start_time", $"after_exp.start_time").withColumn(
"end_time", $"after_exp.end_time").withColumn(
"area", $"after_exp.area").drop("after_exp", "after")
val dfResult = dfSumamry1.unionAll(dfSummary2)
但是,我想知道是否有更优雅的方法来做到这一点。谢谢。
【问题讨论】:
-
分开做然后联合或加入 id 就是我所做的。
标签: scala apache-spark apache-spark-sql explode