Spark Scala Dataframe将Array of Array列转换为Map列

时间:2017-07-14 18:06:51

标签: scala apache-spark apache-spark-sql

我是Scala的新手。  我有一个带字段的数据框

ID:string, Time:timestamp, Items:array(struct(name:string,ranking:long))

我想将 Items 字段的每一行转换为一个hashmap,其中 name 为关键字。 我不太清楚如何做到这一点。

2 个答案:

答案 0 :(得分:4)

这可以使用UDF完成:

import spark.implicits._
import org.apache.spark.sql.functions._
import org.apache.spark.sql.Row

// Sample data:
val df = Seq(
  ("id1", "t1", Array(("n1", 4L), ("n2", 5L))),
  ("id2", "t2", Array(("n3", 6L), ("n4", 7L)))
).toDF("ID", "Time", "Items")

// Create UDF converting array of (String, Long) structs to Map[String, Long]
val arrayToMap = udf[Map[String, Long], Seq[Row]] {
  array => array.map { case Row(key: String, value: Long) => (key, value) }.toMap
}

// apply UDF
val result = df.withColumn("Items", arrayToMap($"Items"))

result.show(false)
// +---+----+---------------------+
// |ID |Time|Items                |
// +---+----+---------------------+
// |id1|t1  |Map(n1 -> 4, n2 -> 5)|
// |id2|t2  |Map(n3 -> 6, n4 -> 7)|
// +---+----+---------------------+

如果没有UDF(仅使用Spark的内置函数),我看不到这样做的方法。

答案 1 :(得分:0)

从 2.4.0 开始,可以使用 map_from_entries

import spark.implicits._
import org.apache.spark.sql.functions._

val df = Seq(
  (Array(("n1", 4L), ("n2", 5L))),
  (Array(("n3", 6L), ("n4", 7L)))
).toDF("Items")

df.select(map_from_entries($"Items")).show

/*
+-----------------------+
|map_from_entries(Items)|
+-----------------------+
|     [n1 -> 4, n2 -> 5]|
|     [n3 -> 6, n4 -> 7]|
+-----------------------+
*/