我写了一个函数,我试图通过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;函数并将其作为参数传递,但它并不喜欢将列表作为“点亮”。
答案 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"))
希望它会对你的情况有所帮助。