我需要在DataFrame上定义自定义方法。什么是更好的方法?解决方案应该是可扩展的,因为我打算定义大量自定义方法。
我当前的方法是创建一个以DataFrame
为参数的类(比如MyClass
),在其中定义我的自定义方法(比如customMethod
),并定义一个隐式方法,该方法将DataFrame
转换为MyClass
。
implicit def dataFrametoMyClass(df: DataFrame): MyClass = new MyClass(df)
因此,我可以调用:
dataFrame.customMethod()
这是正确的做法吗?公开征求建议。
你的路就是你要走的路(参见[1])。尽管我解决了一个有点不同的问题,但方法仍然是相似的:
object ExtraDataFrameOperations {
object implicits {
implicit def dFWithExtraOperations(df: DataFrame) = DFWithExtraOperations(df)
}
}
case class DFWithExtraOperations(df: DataFrame) {
def customMethod(param: String) : DataFrame = {
// do something fancy with the df
// or delegate to some implementation
//
// here, just as an illustrating example: do a select
df.select( df(param) )
}
}
要在DataFrame
上使用新的customMethod
方法:
import ExtraDataFrameOperations.implicits._
val df = ...
val otherDF = df.customMethod("hello")
您也可以使用隐式类
,而不是使用隐式方法
(见上文):
object ExtraDataFrameOperations {
implicit class DFWithExtraOperations(df : DataFrame) {
def customMethod(param: String) : DataFrame = {
// do something fancy with the df
// or delegate to some implementation
//
// here, just as an illustrating example: do a select
df.select( df(param) )
}
}
}
import ExtraDataFrameOperations._
val df = ...
val otherDF = df.customMethod("hello")
如果您想阻止额外的导入
,请将对象
ExtraDataFrame操作
转换为包对象
,并将其存储在包内名为package.scala
的文件中。
[1]M. Odersky的原始博客“皮条客我的图书馆”可在http://www.artima.com/weblogs/viewpost.jsp?thread=179766
有一个稍微简单的方法:只需将MyClass
声明为隐式
implicit class MyClass(df: DataFrame) { def myMethod = ... }
这会自动创建隐式转换方法(也称为 MyClass
)。您还可以通过添加扩展 AnyVal
来使其成为值类,这通过在运行时实际不创建 MyClass
实例来避免一些开销,但这在实践中不太可能重要。
最后,将MyClass
放入包对象
将允许您在该包中的任何位置使用新方法,而不需要导入MyClass
,这对您来说可能是一个好处或缺点。
我认为您应该在DataFrame和您的自定义包装器之间添加一个隐式转换,但是使用一个隐式的class——这应该是最容易使用的,并且您将在一个公共的地方存储您的自定义方法。
implicit class WrappedDataFrame(val df: DataFrame) {
def customMethod(String arg1, int arg2) {
...[do your stuff here]
}
...[other methods you consider useful, getters, setters, whatever]...
}
如果隐式包装器在DataFrame的范围内,您可以使用普通的DataFrame,就好像它是您的包装器一样,即:
df.customMethod(“test”, 100)