将行转换为spark scala中的map

时间:2017-09-11 12:12:06

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

我在数据框中有一行,我想将其转换为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)

有什么想法吗?

4 个答案:

答案 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)