【发布时间】:2018-03-31 08:01:02
【问题描述】:
如何规范化主要由嵌套数组组成的 spark 数据帧?
case class FooBar(id:String, foo:Seq[String], bar:String, baz: Seq[String])
val f = Seq(FooBar("thinga", Seq("1 "), "1 2 3 ", Seq("2 ")),
FooBar("thinga", Seq("1 2 3 4 "), " 0 0 0 ", Seq("2 3 4 5 ")),
FooBar("thingb", Seq("1 2 "), "1 2 3 4 5 ", Seq("1 2 ")),
FooBar("thingb", Seq("0 ", "0 ", "0 "), "1 2 3 4 5 ", Seq("1 2 3 "))).toDS
f.printSchema
f.show(false)
+------+------------+----------+----------+
| id| foo| bar| baz|
+------+------------+----------+----------+
|thinga| [1 ]| 1 2 3 | [2 ]|
|thinga| [1 2 3 4 ]| 0 0 0 |[2 3 4 5 ]|
|thingb| [1 2 ]|1 2 3 4 5 | [1 2 ]|
|thingb|[0 , 0 , 0 ]|1 2 3 4 5 | [1 2 3 ]|
+------+------------+----------+----------+
scala> f.printSchema
root
|-- id: string (nullable = true)
|-- foo: array (nullable = true)
| |-- element: string (containsNull = true)
|-- bar: string (nullable = true)
|-- baz: array (nullable = true)
| |-- element: string (containsNull = true)
我想要一个像explode这样的东西,它将保留(id,foo,bar,baz)的模式,但为数组的每个值返回一个单独的记录。最终结果不应再包含数组。
Foo 和 baz 是相关的。他们的顺序不能被扭曲。它们总是具有相同的长度,并且 foo 的第一个值与 baz 的第一个值相关 - 依此类推。也许我应该先将它们组合成一个列/结构?
最终结果应该类似于:
+------+------------+----------+----------+
| id| foo| bar| baz|
+------+------------+----------+----------+
|thinga| 1 | 1 | 2 |
|thinga| 1 | 2 | 2 |
|thinga| 1 | 3 | 2 |
|thinga| 1 | 0 |2 |
|thinga| 2 | 0 |3 |
|thinga| 3 | 0 |4 |
|thinga| 4 | 0 |5 |
|thinga| 1 | 0 |2 |
|thinga| 2 | 0 |3 |
|thinga| 3 | 0 |4 |
|thinga| 4 | 0 |5 |
|thinga| 1 | 0 |2 |
|thinga| 2 | 0 |3 |
|thinga| 3 | 0 |4 |
|thinga| 4 | 0 |5 |
....
|thingb|0 |1 | 1 |
|thingb|0 |2 | 2 |
|thingb|0 |3 | 3 |
|thingb|0 |4 | 1 |
|thingb|0 |5 | 2 |
|thingb|0 |1 | 3 |
|thingb|0 |2 | 1 |
|thingb|0 |3 | 2 |
|thingb|0 |4 | 3 |
|thingb|0 |5 | 1 |
|thingb|0 |1 | 2 |
|thingb|0 |2 | 3 |
|thingb|0 |3 | 1 |
|thingb|0 |4 | 2 |
|thingb|0 |5 | 3 |
+------+------------+----------+----------+
编辑
部分相关的问题 - Explode (transpose?) multiple columns in Spark SQL table
【问题讨论】:
-
你看过posexplode()spark.apache.org/docs/latest/api/scala/…
-
我玩过它 - 但还没有达到预期的效果。
-
您的数据很奇怪,您的数组仅包含 1 个元素(空格分隔),
bar在您的示例中也不是数组,但您仍想“爆炸”它? -
你好@GeorgHeiler 如果你的数据被美化成这样,那将是一个问题:
val f = Seq(FooBar("thinga", Seq("1"), "1 2 3", Seq("2")), FooBar("thinga", Seq("1", "2", "3", "4"), "0 0 0", Seq("2", "3", "4", "5")), FooBar("thingb", Seq("1", "2"), "1 2 3 4 5", Seq("1", "2")), FooBar("thingb", Seq("0", "0", "0"), "1 2 3 4 5", Seq("1", "2", "3"))).toDS() -
这将从 seq 中删除空间,并将在 seq 中包含多个项目而不是一个项目
标签: arrays apache-spark struct apache-spark-sql spark-dataframe