将行转换为Spark Scala中的地图



我有一个来自数据框的行,我想将其转换为映射列名称为该列中的值的映射列名。

有一种简单的方法吗?

我是为

之类的字符串值做的
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
}

相关内容

  • 没有找到相关文章