使用 SCALA 解析嵌套数据
Posted
技术标签:
【中文标题】使用 SCALA 解析嵌套数据【英文标题】:Parse nested data using SCALA 【发布时间】:2017-11-13 11:41:33 【问题描述】:我的数据框如下:
ColA ColB ColC
1 [2,3,4] [5,6,7]
我需要把它转换成下面的
ColA ColB ColC
1 2 5
1 3 6
1 4 7
有人可以帮助编写 SCALA 中的代码吗?
【问题讨论】:
【参考方案1】:您可以通过UDF
和explode
压缩列来zip
两个数组列,如下所示:
val df = Seq(
(1, Seq(2, 3, 4), Seq(5, 6, 7))
).toDF("ColA", "ColB", "ColC")
def zip = udf(
(x: Seq[Int], y: Seq[Int]) => x zip y
)
val df2 = df.select($"ColA", zip($"ColB", $"ColC").as("BzipC")).
withColumn("BzipC", explode($"BzipC"))
val df3 = df2.select($"ColA", $"BzipC._1".as("ColB"), $"BzipC._2".as("ColC"))
df3.show
+----+----+----+
|ColA|ColB|ColC|
+----+----+----+
| 1| 2| 5|
| 1| 3| 6|
| 1| 4| 7|
+----+----+----+
【讨论】:
【参考方案2】:我在这里提出的想法有点复杂,需要您使用map
来组合ColB
和ColC
的两个数组。然后使用explode
函数来分解组合数组。最后将分解后的组合数组提取到不同的列。
import org.apache.spark.sql.functions._
val tempDF = df.map(row =>
val colB = row(1).asInstanceOf[mutable.WrappedArray[Int]]
val colC = row(2).asInstanceOf[mutable.WrappedArray[Int]]
var array = Array.empty[(Int, Int)]
for(loop <- 0 to colB.size-1)
array = array :+ (colB(loop), colC(loop))
(row(0).asInstanceOf[Int], array)
)
.toDF("ColA", "ColB")
.withColumn("ColD", explode($"ColB"))
tempDF.withColumn("ColB", $"ColD._1").withColumn("ColC", $"ColD._2").drop("ColD").show(false)
这会给你结果
+----+----+----+
|ColA|ColB|ColC|
+----+----+----+
|1 |2 |5 |
|1 |3 |6 |
|1 |4 |7 |
+----+----+----+
【讨论】:
【参考方案3】:您还可以使用 HiveQL 中的 posexplode
和 lateral view
的组合
sqlContext.sql("""
select 1 as colA, array(2,3,4) as colB, array(5,6,7) as colC
""").registerTempTable("test")
sqlContext.sql("""
select
colA , b as colB, c as colC
from
test
lateral view
posexplode(colB) columnB as seqB, b
lateral view
posexplode(colC) columnC as seqC, c
where
seqB = seqC
""" ).show
+----+----+----+
|colA|colB|colC|
+----+----+----+
| 1| 2| 5|
| 1| 3| 6|
| 1| 4| 7|
+----+----+----+
致谢:https://***.com/a/40614822/7224597 ;)
【讨论】:
以上是关于使用 SCALA 解析嵌套数据的主要内容,如果未能解决你的问题,请参考以下文章