Spark - 将映射转换为单行数据帧



在我的应用程序中,我需要从 Map 创建一个单行数据帧。

这样地图就像

("col1" -> 5, "col2" -> 10, "col3" -> 6)

将转换为具有单行的数据帧,映射键将成为列的名称。

col1 | col2 | col3
5    | 10   | 6

如果你想知道我为什么要这个 - 我只需要使用MongoSpark连接器将一个带有一些统计信息的文档保存到MongoDB中,该连接器允许保存DF和RDD。

我认为对

列名进行排序无论如何都不会有什么坏处。

  import org.apache.spark.sql.types._
  val map = Map("col1" -> 5, "col2" -> 6, "col3" -> 10)
  val (keys, values) = map.toList.sortBy(_._1).unzip
  val rows = spark.sparkContext.parallelize(Seq(Row(values: _*)))
  val schema = StructType(keys.map(
    k => StructField(k, IntegerType, nullable = false)))
  val df = spark.createDataFrame(rows, schema)
  df.show()

给:

+----+----+----+
|col1|col2|col3|
+----+----+----+
|   5|   6|  10|
+----+----+----+

这个想法很简单:将映射转换为元组列表,解压缩,将键转换为模式,将值转换为单条目行 RDD,从两个部分构建数据帧(createDataFrame的接口在那里有点奇怪,接受java.util.List和厨房水槽,但由于某种原因不接受通常的 scala List(。

在这里你去:

val map: Map[String, Int] = Map("col1" -> 5, "col2" -> 6, "col3" -> 10)
val df = map.tail
  .foldLeft(Seq(map.head._2).toDF(map.head._1))((acc,curr) => acc.withColumn(curr._1,lit(curr._2)))

df.show()
+----+----+----+
|col1|col2|col3|
+----+----+----+
|   5|   6|  10|
+----+----+----+

Rapheal的答案略有不同。您可以创建一个虚拟列 DF (1*1(,然后使用 foldLeft 添加映射元素,最后删除虚拟列。这样,您的foldLeft就直接且易于记忆。

val map: Map[String, Int] = Map("col1" -> 5, "col2" -> 6, "col3" -> 10)
val f = Seq("1").toDF("dummy")
map.keys.toList.sorted.foldLeft(f) { (acc,x) => acc.withColumn(x,lit(map(x)) ) }.drop("dummy").show(false)
+----+----+----+
|col1|col2|col3|
+----+----+----+
|5   |6   |10  |
+----+----+----+

最新更新