【发布时间】: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 中的代码吗?
【问题讨论】:
标签: scala apache-spark
我的数据框如下:
ColA ColB ColC
1 [2,3,4] [5,6,7]
我需要把它转换成下面的
ColA ColB ColC
1 2 5
1 3 6
1 4 7
有人可以帮助编写 SCALA 中的代码吗?
【问题讨论】:
标签: scala apache-spark
您可以通过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|
+----+----+----+
【讨论】:
我在这里提出的想法有点复杂,需要您使用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 |
+----+----+----+
【讨论】:
您还可以使用 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|
+----+----+----+
【讨论】: