Spark: Как сопоставить Python с Scala или функциями, определенными пользователем Java?

Скажем, например, что моя команда выбрала Python в качестве эталонного языка для разработки с помощью Spark. Но позже по соображениям производительности мы хотели бы разработать конкретные Scala или специфичные для Java librairies, чтобы сопоставить их с нашим кодом Python (что-то похожее на заглушки Python с Scala или скелетами Java).

Как вы считаете, возможно ли связать новые настраиваемые методы Python с капотом с некоторыми функциями Scala или Java User Defined?

Ответ 1

Искра 2. 1+

Вы можете использовать SQLContext.registerJavaFunction:

Зарегистрируйте java UDF, чтобы он мог использоваться в операторах SQL.

для которого требуется name, полное имя класса Java и необязательный тип возвращаемого значения. К сожалению, на данный момент он может использоваться только в операторах SQL (или с помощью expr/selectExpr) и требует Java org.apache.spark.sql.api.java.UDF*:

scalaVersion := "2.11.8"

libraryDependencies ++= Seq(
  "org.apache.spark" %% "spark-sql" % "2.1.0"
)
package com.example.spark.udfs

import org.apache.spark.sql.api.java.UDF1

class addOne extends UDF1[Integer, Integer] {
  def call(x: Integer) = x + 1
} 
sqlContext.registerJavaFunction("add_one", "com.example.spark.udfs.addOne")
sqlContext.sql("SELECT add_one(1)").show()

## +------+
## |UDF(1)|
## +------+
## |     2|
## +------+

Версия независимая:

Я бы не сказал, что это поддерживается, но это, безусловно, возможно. Все функции SQL, доступные в настоящее время в PySpark, - это просто обертки вокруг Scala API.

Предположим, я хочу повторно использовать GroupConcat UDAF, который я создал как ответ на замену SPARK SQL для функции агрегации mysql GROUP_CONCAT, и она находится в пакете com.example.udaf:

from pyspark.sql.column import Column, _to_java_column, _to_seq
from pyspark.sql import Row

row = Row("k", "v")
df = sc.parallelize([
    row(1, "foo1"), row(1, "foo2"), row(2, "bar1"), row(2, "bar2")]).toDF()

def groupConcat(col):
    """Group and concatenate values for a given column

    >>> df = sqlContext.createDataFrame([(1, "foo"), (2, "bar")], ("k", "v"))
    >>> df.select(groupConcat("v").alias("vs"))
    [Row(vs=u'foo,bar')]
    """
    sc = SparkContext._active_spark_context
    # It is possible to use java_import to avoid full package path
    _groupConcat = sc._jvm.com.example.udaf.GroupConcat.apply
    # Converting to Seq to match apply(exprs: Column*)
    return Column(_groupConcat(_to_seq(sc, [col], _to_java_column)))

df.groupBy("k").agg(groupConcat("v").alias("vs")).show()

## +---+---------+
## |  k|       vs|
## +---+---------+
## |  1|foo1,foo2|
## |  2|bar1,bar2|
## +---+---------+

На мой вкус слишком много ведущих подчеркиваний, но, как вы видите, это можно сделать.

Относится к: