不使用UDF从dataframe访问scala映射
我有一个Spark(1.6版)不使用UDF从dataframe访问scala映射,scala,apache-spark,apache-spark-sql,rdd,user-defined-functions,Scala,Apache Spark,Apache Spark Sql,Rdd,User Defined Functions,我有一个Spark(1.6版)Dataframe,我想添加一个包含在Scala映射中的值的列,这是我的简化代码: val map = Map("VAL1" -> 1, "VAL2" -> 2) val df2 = df.withColumn("newVal", map(col("key"))) 这段代码不起作用,显然我收到了以下错误,因为映射在接收列时需要字符串值: found : org.apache.spark.sql.Column required: String 我能
Dataframe
,我想添加一个包含在Scala映射中的值的列,这是我的简化代码:
val map = Map("VAL1" -> 1, "VAL2" -> 2)
val df2 = df.withColumn("newVal", map(col("key")))
这段代码不起作用,显然我收到了以下错误,因为映射在接收列时需要字符串值:
found : org.apache.spark.sql.Column
required: String
我能做到这一点的唯一方法是使用UDF:
val map = Map("VAL1" -> 1, "VAL2" -> 2)
val myUdf = udf{ value:String => map(value)}
val df2 = df.withColumn("newVal", myUdf($"key"))
如果可能的话,我希望避免使用UDF
是否有其他仅使用DataFrame API的解决方案可用(我也希望避免将其转换为RDD)?TL;DR只需使用
udf
对于您使用的版本(根据您的评论,Spark 1.6)没有不需要udf
或map
覆盖RDD
/数据集的解决方案
在更高版本中,您可以:
- 使用
map
函数(2.0或更高版本)创建literalMapType
列
import org.apache.spark.sql.functions
val map = functions.map(
Map("VAL1" -> 1, "VAL2" -> 2)
.flatMap { case (k, v) => Seq(k, v) } .map(lit) .toSeq: _*
)
map($"key")
typedLit
(2.2或更高版本)创建literalMapType
列
val map = functions.typedLit(Map("VAL1" -> 1, "VAL2" -> 2))
map($"key")
直接使用
参考您可以将地图转换为数据帧,并使用此数据帧与现有数据帧之间的连接。因为Map数据帧非常小,所以它应该是一个广播连接,并且避免了洗牌阶段的需要
让Spark知道如何使用广播连接如下所述:您可以使用数据集
或转换为RDD,获取映射值,然后再次转换为dataframe。我想我不能,因为我使用的是Spark 1.6,数据集是Beta版。如果可能的话,您能提供一个仅使用API数据帧的示例吗?我更新了我的问题谢谢@mattinbits,这就成功了。我重构了代码,创建了一个新的数据框架
,并将其与现有的数据框架连接起来