我有一个带有两列的Spark流数据框架。一个Integer id列和一个MapType列,其中Integer Id作为键,而JSON对象作为值。
---------------------------------------------------------------------------------------------------------------
id objects
---------------------------------------------------------------------------------------------------------------
1 | (1 -> {"id" : 1, "type": "jpeg"}, 2 -> {"id" : 2, "type": "gif"}, 3 -> {"id" : 3, "type": "png"})
5 | (1 -> {"id" : 1, "type": "jpeg"}, 2 -> {"id" : 2, "type": "gif"}, 3 -> {"id" : 3, "type": "png"})
2 | (1 -> {"id" : 1, "type": "jpeg"}, 2 -> {"id" : 2, "type": "gif"}, 3 -> {"id" : 3, "type": "png"})
---------------------------------------------------------------------------------------------------------------
我想构造一个新数据框,该数据框具有一个包含其键与id列匹配的JSON对象的列。
----------------------------------------------------------------------
objects
----------------------------------------------------------------------
{"id" : 1, "type": "jpeg"}
{"id" : 2, "type": "gif" }
----------------------------------------------------------------------
执行此操作的最佳方法是什么?我实现了一个Scala udf,它执行查找并返回相应的对象值,但是想知道是否可以使用内置的Spark函数来完成相同的操作。
我试图做这样的事情:
df.withColumn("obj", $"objects".getItem($"id"))
但是会引发异常:
java.lang.RuntimeException: Unsupported literal type class org.apache.spark.sql.ColumnName
这很有意义,因为$"id"
是列类型。但是,如果执行收集操作,将会导致我希望避免的操作。
答案 0 :(得分:1)
不需要UDF,您可以使用内置功能来执行此操作。但是,您不能使用getItem
,而是可以从Map中获取值,如下所示:
df.withColumn("value", $"objects"($"id"))
要创建新的数据框并删除地图中ID不存在的行,
df.select($"objects"($"id").as("objects")).na.drop
这会给你
+-------------------------+
|objects |
+-------------------------+
|{"id": 1, "type": "jpeg"}|
|{"id": 3, "type": "png"} |
+-------------------------+