【问题标题】:Get value from a map for a column value as a key in spark dataframes从映射中获取列值的值作为火花数据帧中的键
【发布时间】:2019-09-17 16:10:19
【问题描述】:

我要从列值作为键的映射中获取一个值并创建一个新列

我已经尝试了以下

val testMap = Map("abc" -> "1234", "xyz" -> "3456")

def checkthemap (testmap: Map[String, String], key: String) : String = {
    val value = testmap.get(key)
    if (value == null) "" else value.toString
}

val testDF = analysis
    .withColumn("test", lit(checkthemap(testMap,$"col")))

方法接受字符串而不是列。如何更改我的 withColumn 语句以将列值作为字符串发送到方法。

【问题讨论】:

    标签: scala apache-spark dataframe


    【解决方案1】:

    从 spark 2.4.x 甚至更简单

    List(Map("a" -> "b")).toDF("map").select("map.a").show()
    

    【讨论】:

      【解决方案2】:

      我对上一个答案有一些问题,因为我无法在带有 element_at 的列中添加。尝试(火花 3+)

      df.withColumn(soureColName, map_values(map_filter(typedLit(testMap),(k, _) => k === col("id")))(0))
      

      【讨论】:

        【解决方案3】:

        我认为你可以使用内置函数 element_at。

        它的定义是:如果列是数组,则返回给定索引处的数组元素。 如果列是映射,则返回给定键的值。

        import org.apache.spark.sql.functions.{element_at, col, typedLit}
        df.withColumn("value", element_at(typedLit(testMap), col("colName")))
        

        【讨论】:

        • element_at 接收一个以键的数据类型作为第二个参数的字面量,因此使用列对象代替会引发异常。
        【解决方案4】:

        我建议使用UDF(用户定义函数),将列作为key 用于传入的查找Map 以返回对应的Map 值,如下所示:

        import org.apache.spark.sql.functions._
        import spark.implicits._
        
        def getMapValue(m: Map[String, String], defaultValue: String) = udf{
          (key: String) => m.getOrElse(key, defaultValue)
        }
        
        val df = Seq(
          (1, "a"), (2, "b"), (3, "c")
        ).toDF("id", "key")
        
        val lookupMap = Map("a" -> "xx", "c" -> "zz")
        
        df.withColumn("value", getMapValue(lookupMap, "")($"key")).show
        // +---+---+-----+
        // | id|key|value|
        // +---+---+-----+
        // |  1|  a|   xx|
        // |  2|  b|     |
        // |  3|  c|   zz|
        // +---+---+-----+
        

        编辑:有关使用内置 Spark 函数的解决方案的其他答案,这些函数通常比 UDF 执行得更好。

        【讨论】:

          【解决方案5】:

          公认的答案是非常低效并且不必要地复杂。相反,您应该将 testMap 视为文字。导入以下内容

          import org.apache.spark.sql.functions.{coalesce, lit, typedLit}
          

          将地图转换为列:

          val testMapCol = typedLit(testMap)
          

          然后选择:

          df.withColumn("value", coalesce(testMapCol($"col"), lit(""))
          

          【讨论】:

          • 出于某种原因,我不想为列或数据框创建地图。我想从方法本身访问它。还有其他选择吗?
          • @user11425401 关于这个 UDF 问题的任何建议请stackoverflow.com/questions/63935600/…
          猜你喜欢
          • 2015-10-05
          • 1970-01-01
          • 2023-03-29
          • 2018-03-14
          • 2016-04-04
          • 1970-01-01
          • 1970-01-01
          • 2018-02-15
          • 2018-08-21
          相关资源
          最近更新 更多