使用Map替换Spark中的列值

时间:2019-06-12 08:29:19

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

我必须将列列表映射到Spark数据集中的另一列:这样思考

val translationMap: Map[Column, Column] = Map(
  lit("foo") -> lit("bar"),
  lit("baz") -> lit("bab")
)

我有一个像这样的数据框:

val df = Seq("foo", "baz").toDF("mov")

所以我打算像这样执行翻译:

df.select(
  col("mov"),
  translationMap(col("mov"))
)

但是这段代码会引发以下错误

key not found: movs
java.util.NoSuchElementException: key not found: movs

有没有一种方法可以执行这种翻译而不将数百个when连接在一起?认为translationMap可能有很多对键值。

2 个答案:

答案 0 :(得分:5)

您应该使用包含地图文字的Map[Column, Column]代替Column

import org.apache.spark.sql.functions.typedLit

val translationMap: Column = typedLit(Map(
  "foo" -> "bar",
  "baz" -> "bab"
))

其余代码可以保持不变:

df.select(
  col("mov"),
  translationMap(col("mov"))
).show
+---+---------------------------------------+
|mov|keys: [foo,baz], values: [bar,bab][mov]|
+---+---------------------------------------+
|foo|                                    bar|
|baz|                                    bab|
+---+---------------------------------------+

答案 1 :(得分:0)

您不能在分布式数据框中引用像这样在驱动程序上声明的Scala集合。一种替代方法是使用UDF,如果您的数据集很大,则该性能将不高效,因为Spark无法对UDF进行优化。

run()

另一种解决方案是将val translationMap = Map( "foo" -> "bar" , "baz" -> "bab" ) val getTranslationValue = udf ((x: String)=>translationMap.getOrElse(x,null.asInstanceOf[String]) ) df.select(col("mov"), getTranslationValue($"mov").as("value") ).show //+---+-----+ //|mov|value| //+---+-----+ //|foo| bar| //|baz| bab| //+---+-----+ 作为Map加载,并以DataSet[(String, String)]为键将两个数据集连接起来。