我必须将列列表映射到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
可能有很多对键值。
答案 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)]
为键将两个数据集连接起来。