从地图获取值以将列值作为Spark数据框中的键

时间:2019-04-29 03:14:28

标签: scala apache-spark dataframe

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

我尝试了以下

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语句以将列值作为字符串发送给方法。

4 个答案:

答案 0 :(得分:3)

公认的答案是效率很低,而且不必要地复杂。相反,您应该只将testMap当作文字。导入以下

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

将地图转换为列:

val testMapCol = typedLit(testMap)

,然后选择:

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

答案 1 :(得分:2)

我建议使用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更好。

答案 2 :(得分:1)

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

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

答案 3 :(得分:0)

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

其定义是:如果column是array,则返回给定值处索引数组的元素。 如果列是map,则返回给定键值的值。

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