如何在Spark中动态创建UDF?

时间:2016-12-22 00:56:44

标签: scala apache-spark apache-spark-sql

我有DataFrame我想动态创建多个UDF以确定某些行是否匹配。我现在只是测试一个例子。我的测试代码如下所示。

//create the dataframe
import spark.implicits._
val df = Seq(("t","t"), ("t", "f"), ("f", "t"), ("f", "f")).toDF("n1", "n2")

//create the scala function
def filter(v1: Seq[Any], v2: Seq[String]): Int = {
  for (i <- 0 until v1.length) {
    if (!v1(i).equals(v2(i))) {
      return 0
    }
  }
  return 1
}

//create the udf
import org.apache.spark.sql.functions.udf
val fudf = udf(filter(_: Seq[Any], _: Seq[String]))

//apply the UDF
df.withColumn("filter1", fudf(Seq($"n1"), Seq("t"))).show() 

但是,当我运行最后一行时,我收到以下错误。

:30: error: not found: value df
       df.withColumn("filter1", fudf($"n1", Seq("t"))).show()
       ^
:30: error: type mismatch;
 found   : Seq[String]
 required: org.apache.spark.sql.Column
       df.withColumn("filter1", fudf($"n1", Seq("t"))).show()
                                               ^

关于我做错的任何想法?注意,我使用的是Scala v2.11.x和Spark 2.0.x.

另一方面,如果我们可以解决这个问题,那就是动态&#34; UDF问题/关注,我的用例是将它们添加到数据帧中。有了一些测试代码如下,它需要永远(它甚至没有完成,我不得不ctrl-c爆发)。我猜测在for循环中做一堆.withColumn在Spark中是个坏主意。如果是这样,请告诉我,我会完全放弃这种方法。

import spark.implicits._
val df = Seq(("t","t"), ("t", "f"), ("f", "t"), ("f", "f")).toDF("n1", "n2")

import org.apache.spark.sql.functions.udf
val fudf = udf( (x: String) => if (x.equals("t")) 1 else 0)

var df2 = df
for (i <- 0 until 10000) {
  df2 = df2.withColumn("filter"+i, fudf($"n1"))
}

1 个答案:

答案 0 :(得分:1)

lit()

中附上&#34; t&#34;
df.withColumn("filter1", fudf($"n1", Seq(lit("t")))).show()

尝试在sqlContext上注册UDF。

Spark 2.0 UDF registration

相关问题