在我的应用程序中,我需要从Map创建单行DataFrame。
这样的地图就像
("col1" -> 5, "col2" -> 10, "col3" -> 6)
将转换为具有单行的DataFrame,并且映射键将成为列的名称。
col1 | col2 | col3
5 | 10 | 6
如果您想知道我为什么要这样 - 我只需要使用MongoSpark连接器将一些带有一些统计信息的文档保存到MongoDB中,这样可以节省DF和RDD。
答案 0 :(得分:5)
我认为排序列名称无论如何都不会受到伤害。
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|
+----+----+----+
这个想法很简单:将map转换为元组列表,解压缩,将键转换为模式,将值转换为单条目行RDD,从两个部分构建数据帧(interface for createDataFrame
有点奇怪的是,接受java.util.List
和厨房水槽,但由于某种原因不接受通常的scala List
。
答案 1 :(得分:0)
你去:
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|
+----+----+----+
答案 2 :(得分:0)
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 |
+----+----+----+