在spark中爆发另一个地图类型的地图类型列

时间:2018-03-04 17:13:12

标签: scala apache-spark

我的数据集架构看起来像这样

root
 |-- col1: string (nullable = false)
 |-- col2: string (nullable = false)
 |-- col3: timestamp (nullable = false)
 |-- col4: map (nullable = false)
 |    |-- key: string
 |    |-- value: map (valueContainsNull = true)
 |    |    |-- key: integer
 |    |    |-- value: long (valueContainsNull = true)

col4是一种地图类型,但在其中,还有另一张地图。

我可以使用explode(col4)来获取

root
 |-- col1: string (nullable = false)
 |-- col2: string (nullable = false)
 |-- col3: timestamp (nullable = false)
 |-- key: string (nullable = false)
 |-- value: map (nullable = true)
 |    |-- key: integer
 |    |-- value: long (valueContainsNull = true)

我现在应该如何分解value列?

一种愚蠢的方法是重命名key列,然后再次展开value列...但我正在努力做到这一点。

1 个答案:

答案 0 :(得分:1)

您需要定义udf功能以将地图 col4列展平为

import org.apache.spark.sql.functions._
def flatNestedMap = udf((maps: Map[String,Map[Int, Long]])=> maps.flatMap(x => x._2.map(y => (x._1, y._1, y._2))).toArray)

然后,您可以在explode函数返回的列上使用一个udf,然后在select必要的列中使用

df.withColumn("col4", explode(flatNestedMap(col("col4"))))
    .select(col("col1"), col("col2"), col("col3"), col("col4._1").as("outerKey"), col("col4._2").as("innerKey"), col("col4._3").as("innerValue"))

多数民众赞成。我希望答案很有帮助