gpt4 book ai didi

scala - 分解具有不同长度的相同类型的多个列

转载 作者:行者123 更新时间:2023-12-01 22:05:08 24 4
gpt4 key购买 nike

我有一个具有以下格式的 spark 数据框需要分解。我检查了其他解决方案,例如 this one .但是,在我的例子中,beforeafter 可以是不同长度的数组。

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” 或“after”

我可以在两个单独的展开中执行此操作,然后在每个展开中制作 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)

但是,我想知道是否有更优雅的方法来做到这一点。谢谢。

最佳答案

你也可以在没有联合的情况下实现这一点。随着数据:

case class Area(start_time: String, end_time: String, area: String)

val df = Seq((
"1", Seq(Area("01:00", "01:30", "10"), Area("02:00", "02:30", "20")),
Seq(Area("07:00", "07:30", "70"), Area("08:00", "08:30", "80"), Area("09:00", "09:30", "90"))
)).toDF("id", "before", "after")

你可以做到

df
.select($"id",
explode(
array(
struct(lit("before").as("type"), $"before".as("data")),
struct(lit("after").as("type"), $"after".as("data"))
)
).as("step1")
)
.select($"id",$"step1.type", explode($"step1.data").as("step2"))
.select($"id",$"type", $"step2.*")
.show()

+---+------+----------+--------+----+
| id| type|start_time|end_time|area|
+---+------+----------+--------+----+
| 1|before| 01:00| 01:30| 10|
| 1|before| 02:00| 02:30| 20|
| 1| after| 07:00| 07:30| 70|
| 1| after| 08:00| 08:30| 80|
| 1| after| 09:00| 09:30| 90|
+---+------+----------+--------+----+

关于scala - 分解具有不同长度的相同类型的多个列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52395281/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com