我在数据框中有一行,我想将其转换为Map [String,Any],它将列名映射到该列的行中的值。
有一种简单的方法吗?
我是为
这样的字符串值做的def rowToMap(row:Row): Map[String, String] = {
row.schema.fieldNames.map(field => field -> row.getAs[String](field)).toMap
}
val myRowMap = rowToMap(myRow)
如果该行包含其他值,而不是像String这样的特定值,则代码变得更加混乱,因为该行没有方法.get(field)
有什么想法吗?
答案 0 :(得分:8)
您可以使用getValuesMap
:
val df = Seq((1, 2.0, "a")).toDF("A", "B", "C")
val row = df.first
获取Map[String, Any]
:
row.getValuesMap[Any](row.schema.fieldNames)
// res19: Map[String,Any] = Map(A -> 1, B -> 2.0, C -> a)
或者你可以得到Map[String, AnyVal]
这个简单的情况,因为这些值不是复杂的对象
row.getValuesMap[AnyVal](row.schema.fieldNames)
// res20: Map[String,AnyVal] = Map(A -> 1, B -> 2.0, C -> a)
注意: getValuesMap
的返回值类型可以标记为任何类型,因此您不能依赖它来确定您拥有但需要的数据类型要记住你从一开始就拥有的东西。
答案 1 :(得分:0)
您可以将dataframe
转换为rdd
并使用简单的map
函数,并使用headernames
形式MAP
形式中的map
最后使用collect
val fn = df.schema.fieldNames
val maps = df.rdd.map(row => fn.map(field => field -> row.getAs(field)).toMap).collect()
答案 2 :(得分:0)
假设您有一个包含以下列的数据框:
[time(TimeStampType), col1(DoubleType), col2(DoubleType)]
您可以这样做:
val modifiedDf = df.map{row =>
val doubleObject = row.getValuesMap(Seq("col1","col2"))
val timeObject = Map("time" -> row.getAs[TimeStamp]("time"))
val map = doubleObject ++ timeObject
}
答案 3 :(得分:0)
假设您有一行没有结构信息,而列标题为数组。
val rdd = sc.parallelize( Seq(Row("test1", "val1"), Row("test2", "val2"), Row("test3", "val3"), Row("test4", "val4")) )
rdd.collect.foreach(println)
val sparkFieldNames = Array("col1", "col2")
val mapRDD = rdd.map(
r => sparkFieldNames.zip(r.toSeq).toMap
)
mapRDD.collect.foreach(println)