我有一个来自数据框的行,我想将其转换为映射列名称为该列中的值的映射列名。
有一种简单的方法吗?
我是为
之类的字符串值做的def rowToMap(row:Row): Map[String, String] = {
row.schema.fieldNames.map(field => field -> row.getAs[String](field)).toMap
}
val myRowMap = rowToMap(myRow)
如果该行包含其他值,而不是字符串之类的特定值,则代码会变得更加混乱,因为该行没有A方法.get(field)
有什么想法?
您可以使用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)
note :可以将getValuesMap
的返回值类型标记为任何类型,因此您不能依靠它来弄清楚您拥有的数据类型,但需要牢记您从一开始就拥有什么。
您可以将dataframe
转换为rdd
并使用简单的map
函数,并在map
函数内的MAP
组中使用headernames
,并最终使用collect
val fn = df.schema.fieldNames
val maps = df.rdd.map(row => fn.map(field => field -> row.getAs(field)).toMap).collect()
,假设您有一排,没有结构信息,将列标题作为数组。
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)
假设您有一个具有这些列的数据框架:
[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
}