Каков наилучший способ определения пользовательских методов в DataFrame?

Мне нужно определить пользовательские методы на DataFrame. Какой лучший способ сделать это? Решение должно быть масштабируемым, так как я намерен определить значительное количество пользовательских методов.

Мой текущий подход заключается в создании класса (скажем, MyClass) с DataFrame в качестве параметра определите мой пользовательский метод (скажем, customMethod) в этом и определить неявный метод, который преобразует DataFrame в MyClass,

implicit def dataFrametoMyClass(df: DataFrame): MyClass = new MyClass(df)

Таким образом я могу позвонить:

dataFrame.customMethod()

Это правильный способ сделать это? Открыт для предложений.

3 ответа

Твой путь - это путь (см. [1]). Хотя я решил это немного по-другому, подход остается схожим:

Возможность 1

Implicits

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) )
  }
}

использование

Чтобы использовать новый customMethod метод на DataFrame:

import ExtraDataFrameOperations.implicits._
val df = ...
val otherDF = df.customMethod("hello")

Возможность 2

Вместо использования implicit method (см. выше), вы также можете использовать implicit class:

Неявный класс

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")

замечание

В случае, если вы хотите предотвратить дополнительные import, повернуть objectExtraDataFrameOperations в package object и сохранить его в файле с именем package.scala в вашем пакете.

Официальная документация / ссылки

[1] Оригинальный блог М.Одерского "Прокачай мою библиотеку" доступен по адресу http://www.artima.com/weblogs/viewpost.jsp?thread=179766

Есть немного более простой подход: просто объявите MyClass какimplicit

implicit class MyClass(df: DataFrame) { def myMethod = ... }

Это автоматически создает метод неявного преобразования (также называетсяMyClass). Вы также можете сделать его классом стоимости, добавивextends AnyValкоторый избегает некоторых накладных расходов, фактически не создаваяMyClassНапример, во время выполнения, но это вряд ли имеет значение на практике.

Наконец, положитьMyClassвpackage object позволит вам использовать новые методы в любом месте этого пакета, не требуя импорта MyClass, что может быть выгодой или недостатком для вас.

Я думаю, что вам следует добавить неявное преобразование между DataFrame и вашей пользовательской оболочкой, но использовать неявные классы - это должно быть самым простым в использовании, и вы будете хранить свои пользовательские методы в одном общем месте.

   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("тест", 100)

Другие вопросы по тегам