我有一个UDF说
val testUDF = udf{s: string=>s.toUpperCase}
我想在一个单独的方法中创建这个UDF,或者可能是另一个类似于实现类的东西,并将它传递给另一个使用它的类。有可能吗?
假设我有一个A类
class A(df: DataFrame) {
def testMethod(): DataFrame = {
val demo=df.select(testUDF(col))
}
}
A类应该能够使用UDF。这可以实现吗?
答案 0 :(得分:0)
如果我理解正确,你会真的想要某种工厂为特定的A类创建这个user-defined-function
。
这可以使用隐式注入的类类来实现。
E.g。 (我必须定义UDF和DataFrame以便能够测试它)
type UDF = String => String
case class DataFrame(col: String) {
def select(in: String) = s"col:$col, in:$in"
}
trait UDFFactory[A] {
def testUDF: UDF
}
implicit object UDFFactoryA extends UDFFactory[AClass] {
def testUDF: UDF = _.toUpperCase
}
class AClass(df: DataFrame) {
def testMethod(implicit factory: UDFFactory[AClass]) = {
val demo = df.select(factory.testUDF(df.col))
println(demo)
}
}
val a = new AClass(DataFrame("test"))
a.testMethod // prints 'col:test, in:TEST'
答案 1 :(得分:0)
就像你提到的那样,在对象体或伴侣类中创建一个与UDF完全相同的方法,
val myUDF = udf((str:String) => { str.toUpperCase })
然后对于某些数据帧df
执行此操作,
val res=df withColumn("NEWCOLNAME", myUDF(col("OLDCOLNAME")))
这会改变这样的事情,
+-------------------+
| OLDCOLNAME |
+-------------------+
| abc |
+-------------------+
到
+-------------------+-------------------+
| OLDCOLNAME | NEWCOLNAME |
+-------------------+-------------------+
| abc | ABC |
+-------------------+-------------------+
让我知道这是否有帮助,干杯。
答案 2 :(得分:0)
将dataframe
视为
+----+
|col1|
+----+
|abc |
|dBf |
|Aec |
+----+
一个udf
函数
import org.apache.spark.sql.functions._
val testUDF = udf{s: String=>s.toUpperCase}
您绝对可以使用其他类中的udf
函数
val demo = df.select(testUDF(col("col1")).as("upperCasedCol"))
应该给你
+-------------+
|upperCasedCol|
+-------------+
|ABC |
|DBF |
|AEC |
+-------------+
但我建议你尽可能使用other functions ,因为udf函数需要对序列化和反序列化的列进行序列化和反序列化,这比其他可用函数消耗时间和内存更多。 UDF功能应该是最后的选择。
您可以使用upper function作为案例
val demo = df.select(upper(col("col1")).as("upperCasedCol"))
这将生成与原始udf
函数
我希望答案很有帮助
<强>更新强>
由于您的问题是询问有关如何调用另一个类或对象中定义的udf函数的信息,这里是方法
假设您有一个对象,您在其中定义了udf函数或我建议的函数
import org.apache.spark.sql.Column
import org.apache.spark.sql.functions._
object UDFs {
def testUDF = udf{s: String=>s.toUpperCase}
def testUpper(column: Column) = upper(column)
}
你的A班就像你的问题,我刚刚添加了另一个功能
import org.apache.spark.sql.DataFrame
import org.apache.spark.sql.functions._
class A(df: DataFrame) {
def testMethod(): DataFrame = {
val demo = df.select(UDFs.testUDF(col("col1")))
demo
}
def usingUpper() = {
df.select(UDFs.testUpper(col("col1")))
}
}
然后你可以从main调用函数,如下所示
import org.apache.spark.sql.SparkSession
object TestUpper {
def main(args: Array[String]): Unit = {
val sparkSession = SparkSession.builder().appName("Simple Application")
.master("local")
.config("", "")
.getOrCreate()
import sparkSession.implicits._
val df = Seq(
("abc"),
("dBf"),
("Aec")
).toDF("col1")
val a = new A(df)
//calling udf function
a.testMethod().show(false)
//calling upper function
a.usingUpper().show(false)
}
}
我想这不仅仅是有用的
答案 3 :(得分:0)
是的,因为函数是scala中可以传递的对象:
import org.apache.spark.sql.expressions.UserDefinedFunction
class A(df: DataFrame, testUdf:UserDefinedFunction) {
def testMethod(): DataFrame = {
df.select(testUdf(col))
}
}