在不使用 UDF 的情况下从数据帧访问 scala 映射
Posted
技术标签:
【中文标题】在不使用 UDF 的情况下从数据帧访问 scala 映射【英文标题】:access scala map from dataframe without using UDFs 【发布时间】:2018-05-18 10:27:42 【问题描述】:我有一个 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
我能做到这一点的唯一方法是使用 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)?
【问题讨论】:
您可以使用DataSet
或转换为RDD,获取地图值,然后再次转换为数据帧。
我想我不能,因为我使用的是 Spark 1.6 并且 DataSet 处于 Beta 版本。如果可能的话,您能否提供一个仅使用 API DataFrame 的示例?我更新了我的问题
【参考方案1】:
TL;DR只需使用udf
。
对于您使用的版本(根据您的评论,Spark 1.6)没有解决方案不需要udf
或map
而不是RDD
/ Dataset
。
在以后的版本中,您可以:
使用map
函数(2.0 或更高版本)创建文字MapType
列
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 或更高版本)创建文字 MapType
列。
val map = functions.typedLit(Map("VAL1" -> 1, "VAL2" -> 2))
map($"key")
并直接使用这些。
参考How to add a constant column in a Spark DataFrame?
【讨论】:
【参考方案2】:您可以将地图转换为数据框,并在此数据框和现有数据框之间使用 JOIN。由于 Map 数据帧非常小,它应该是一个 Broadcast Join 并避免需要一个 shuffle 阶段。
这个答案描述了让 Spark 知道使用广播连接:DataFrame join optimization - Broadcast Hash Join
【讨论】:
感谢@mattinbits,这成功了。我重构了我的代码,创建了一个新的DataFrame
并将其与现有的加入以上是关于在不使用 UDF 的情况下从数据帧访问 scala 映射的主要内容,如果未能解决你的问题,请参考以下文章
如何在不将单独的帧图像写入磁盘的情况下从 C++ 程序中生成的多个图像编码视频?
是否可以在不先将对象作为文件保存到谷歌驱动器的情况下从谷歌 colab 下载对象作为文件?
如何在不登录的情况下从 Instagram 获取 oauth 2 访问令牌(隐式流程)?