如何将整行传递给UDF - Spark DataFrame过滤器

时间:2015-08-04 18:49:02

标签: apache-spark

我正在为具有大量内部结构的复杂JSON数据集编写过滤函数。传递单个列太麻烦了。

所以我声明了以下UDF:

val records:DataFrame = = sqlContext.jsonFile("...")
def myFilterFunction(r:Row):Boolean=???
sqlc.udf.register("myFilter", (r:Row)=>myFilterFunction(r))

我直觉地认为它会像这样工作:

records.filter("myFilter(*)=true")

实际语法是什么?

2 个答案:

答案 0 :(得分:22)

在调用函数时必须使用struct()函数构造行,请按照以下步骤操作。

导入行,

import org.apache.spark.sql._

定义UDF

def myFilterFunction(r:Row) = {r.get(0)==r.get(1)} 

注册UDF

sqlContext.udf.register("myFilterFunction", myFilterFunction _)

创建dataFrame

val records = sqlContext.createDataFrame(Seq(("sachin", "sachin"), ("aggarwal", "aggarwal1"))).toDF("text", "text2")

使用UDF

records.filter(callUdf("myFilterFunction",struct($"text",$"text2"))).show

当你想要将所有列传递给UDF时。

records.filter(callUdf("myFilterFunction",struct(records.columns.map(records(_)) : _*))).show 

结果:

+------+------+
|  text| text2|
+------+------+
|sachin|sachin|
+------+------+

答案 1 :(得分:3)

scala> inputDF
res40: org.apache.spark.sql.DataFrame = [email: string, first_name: string ... 3 more fields]

scala> inputDF.printSchema
root
 |-- email: string (nullable = true)
 |-- first_name: string (nullable = true)
 |-- gender: string (nullable = true)
 |-- id: long (nullable = true)
 |-- last_name: string (nullable = true)

现在,我想根据性别字段过滤行。我可以使用.filter($"gender" === "Male")来完成此操作,但我想使用.filter(function)

所以,定义了我的匿名函数

val isMaleRow = (r:Row) => {r.getAs("gender") == "Male"}

val isFemaleRow = (r:Row) => { r.getAs("gender") == "Female" }

inputDF.filter(isMaleRow).show()

inputDF.filter(isFemaleRow).show()

我觉得可以以更好的方式完成要求,即不声明为UDF并调用它。