如何将spark数据帧展平为多个Dataframe行

时间:2017-02-22 09:18:22

标签: apache-spark dataframe

嗨我有一个像这样(单行)打印的火花数据框

[abc,WrappedArray(11918,1233),WrappedArray(46734,1234),1487530800317]

所以在一行中我已经包装了数组,我想要将它展平并创建一个数据帧,每个数组都有单个值,例如上面的行应该转换为这样的

[abc,11918,46734,1487530800317]
[abc,1233,1234,1487530800317]

所以我得到了2行而不是1行的数据帧,因此包装数组中的每个对应元素都应该进入新行。

在第一个回答后编辑1: 如果我的输入中有3个数组

,该怎么办?
WrappedArray(46734,1234,[abc,WrappedArray(11918,1233),WrappedArray(46734,1234),WrappedArray(1,2),1487530800317]

我的输出应该是

[abc,11918,46734,1,1487530800317]
[abc,1233,1234,2,1487530800317] 

2 个答案:

答案 0 :(得分:0)

绝对不是最好的解决方案,但这可行:

case class TestFormat(a: String, b: Seq[String], c: Seq[String], d: String)

val data = Seq(TestFormat("abc", Seq("11918","1233"), 
            Seq("46734","1234"), "1487530800317")).toDS

val zipThem: (Seq[String], Seq[String]) => Seq[(String, String)] = _.zip(_)

val udfZip = udf(zipThem)

data.select($"a", explode(udfZip($"b", $"c")) as "tmp", $"d")
    .select($"a", $"tmp._1" as "b", $"tmp._2" as "c", $"d")
    .show

问题在于,默认情况下,您无法确定两个序列的长度是否相等。

可能更好的解决方案是将整个数据帧重新格式化为模拟数据的结构,例如

root
-- a
-- d
-- records
---- b
---- c

答案 1 :(得分:0)

感谢您回答@swebbo,您的答案帮助我完成了这项工作:

我这样做了:

import org.apache.spark.sql.functions.{explode, udf}
import sqlContext.implicits._
val zipColumns = udf((x: Seq[Long], y: Seq[Long], z: Seq[Long]) => (x.zip(y).zip(z)) map {
  case ((a,b),c) => (a,b,c)
})

val flattened = subDf.withColumn("columns", explode(zipColumns($"col3", $"col4", $"col5"))).select(
  $"col1", $"col2",
  $"columns._1".alias("col3"), $"columns._2".alias("col4"), $"columns._3".alias("col5"))
flattened.show

希望这是可以理解的:)