Spark:UDF没有读取已经定义的值

时间:2015-06-08 02:54:12

标签: scala apache-spark

我写了一个函数,我试图通过UDF应用于数据帧。它根据特定列中的值应用类别。该函数使用我之前在代码中定义的值。代码如下所示:

object myFuncs extends App {
  val sc = new SparkContext()
  val sqlContext = new org.apache.spark.sql.SQLContext(sc)
  val categories = List("10","20")

  def makeCategory(value:Double): String = {
    if (value < categories(0)) "< 10"
    else if (value >= categories(0) && value < categories(1)) "10 to 20"
    else ">= 10"
  }

  val myFunc = udf(makeCategory _)
  val df = sqlContext.parquetFile("hdfs:/to/my/file.parquet").withColumn("category", myFunc(col("myColumn")))
}

当它尝试读取函数内的categories变量时,会产生NullPointerException。如果我在函数中明确定义categories变量,这可以正常工作。最终,我希望将其作为一个arg传递给我,因此我无法在函数内定义它。

为什么它不能读取UDF中函数外定义的值的任何解释?有关如何在不明确定义函数值的情况下完成此工作的任何建议?我尝试使用&#39; lit&#39;函数并将其作为参数传递,但它并不喜欢将列表作为“点亮”。

1 个答案:

答案 0 :(得分:0)

简单的解决方案是在查询中传递类别,然后它将正常工作。你必须改变你的功能

def makeCategory(value:Double, categoriesString : String): String = {
 val categories = categoriesString.split(",")
 if (value < categories(0)) "< 10"
 else if (value >= categories(0) && value < categories(1)) "10 to 20"
 else ">= 10"
}

所以现在你可以将这个函数注册为UDT,但你必须像下面这样使用它

val df = sqlContext.parquetFile("hdfs:/to/my/file.parquet").withColumn("category", myFunc(col("myColumn"),"10,20"))

希望它会对你的情况有所帮助。