我希望能够在PySpark中使用Scala函数作为UDF
package com.test
object ScalaPySparkUDFs extends Serializable {
def testFunction1(x: Int): Int = { x * 2 }
def testUDFFunction1 = udf { x: Int => testFunction1(x) }
}
我可以在PySpark中访问testFunction1
并让它返回值:
functions = sc._jvm.com.test.ScalaPySparkUDFs
functions.testFunction1(10)
我希望能够将此功能用作UDF,理想情况是在withColumn
调用中:
row = Row("Value")
numbers = sc.parallelize([1,2,3,4]).map(row).toDF()
numbers.withColumn("Result", testUDFFunction1(numbers['Value']))
我认为这里有一个很有前景的方法: Spark: How to map Python with Scala or Java User Defined Functions?
但是,当对代码进行更改时,使用testUDFFunction1
代替:
def udf_test(col):
sc = SparkContext._active_spark_context
_f = sc._jvm.com.test.ScalaPySparkUDFs.testUDFFunction1.apply
return Column(_f(_to_seq(sc, [col], _to_java_column)))
我明白了:
AttributeError: 'JavaMember' object has no attribute 'apply'
我不明白这一点,因为我相信testUDFFunction1
确实有申请方法?
我不想使用此处找到的类型的表达式: Register UDF to SqlContext from Scala to use in PySpark
任何有关如何完成这项工作的建议都将不胜感激!
答案 0 :(得分:2)
您关联的问题是使用Scala object
。 Scala object
是一个单例,您可以直接使用apply
方法。
在这里你使用一个nullary函数,它返回一个UserDefinedFunction
类的对象,你必须首先调用该函数:
_f = sc._jvm.com.test.ScalaPySparkUDFs.testUDFFunction1() # Note () at the end
Column(_f.apply(_to_seq(sc, [col], _to_java_column)))
答案 1 :(得分:1)
同意@ user6910411,您必须直接在函数上调用apply方法。 因此,您的代码将是。
Scala中的UDF:
import org.apache.spark.sql.expressions.UserDefinedFunction
import org.apache.spark.sql.functions._
object ScalaPySparkUDFs {
def testFunction1(x: Int): Int = { x * 2 }
def getFun(): UserDefinedFunction = udf(testFunction1 _ )
}
PySpark代码:
def test_udf(col):
sc = spark.sparkContext
_test_udf = sc._jvm.com.test.ScalaPySparkUDFs.getFun()
return Column(_test_udf.apply(_to_seq(sc, [col], _to_java_column)))
row = Row("Value")
numbers = sc.parallelize([1,2,3,4]).map(row).toDF()
numbers.withColumn("Result", test_udf(numbers['Value']))