【问题标题】:How to convert scala Array of Maps into Spark df如何将 scala 地图数组转换为 Spark df
【发布时间】:2022-01-21 07:46:28
【问题描述】:

我有 Array[Map[String,String]] 类型的 scala 数组,我想将其转换为 spark df。

输入:- Array(Map("col1" -> "val1"), Map("col2" -> "val2", "col1" -> "val1"), Map("col3" -> "val3") )

预期输出:-

火花df

col1 col2 col3
val1 NA NA
val1 val2 NA
NA NA val3

最好的方法是什么?

【问题讨论】:

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


    【解决方案1】:

    首先提取密钥:

    val input = Seq(Map("col1" -> "val1"), Map("col2" -> "val2", "col1" -> "val1"), Map("col3" -> "val3"))
    val keys = input.flatMap(_.keys.toSeq).distinct
    

    然后,您将需要一个方法来用 null 填充每个 Map 对象上所有不存在的键,如下所示:

    def completeNonExistingValuesWithNull(obj: Map[String, String])(columnNames: String*): Map[String, String] = {
      val nonExistingKeys = columnNames.filterNot(obj.keys.toSeq.contains)
      obj concat Map(
        nonExistingKeys.map { key =>
          key -> (null: String)
        }: _*
      )
    }
    // I would also rather creating a function value to use in
    // map functions easily so I wont need to pass the keys everytime
    val completeNonExistingValues: Map[String, String] => Map[String, String] = 
        obj => completeNonExistingValuesWithNull(obj)(keys: _*)
    

    您需要的另一件事是能够将序列转换为元组,以便为​​您的数据框创建行(因为序列对象被视为具有 ArrayType 结构的单个对象)

    def toProduct(seq: Seq[String]) = seq match {
      case Seq(a, b, c) => (a, b, c)
    }
    

    完成了:

    val completedKeyValues: Seq[Map[String, String]] =
      input.map(completeNonExistingValues)
    
    val objects = completedKeyValues.map(_.values.toSeq).map(toProduct)
    
    import spark.implicits._
    objects.toDF(keys: _*)
    

    【讨论】:

    • 上线Exception in thread "main" java.lang.IllegalArgumentException: requirement failed: The number of columns doesn't match.values.toDF(keys:_*)
    • @DeepGhodasara 你是对的,刚刚修复它。看看吧。
    猜你喜欢
    • 2020-06-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-13
    • 2018-11-30
    • 2017-05-17
    • 1970-01-01
    • 2017-10-10
    相关资源
    最近更新 更多