Spark:如何使用 Scala 或 Java User Defined Functions 映射 Python?

2022-09-01 15:54:52

例如,假设我的团队选择Python作为使用Spark开发的参考语言。但后来出于性能原因,我们希望开发特定的Scala或Java特定的librairies,以便用我们的Python代码映射它们(类似于带有Scala或Java框架的Python存根)。

难道你不认为有可能将新的自定义Python方法与一些Scala或Java用户定义函数进行接口吗?


答案 1

火花 2.1+

您可以使用 SQLContext.registerJavaFunction

注册一个 java UDF,以便它可以在 SQL 语句中使用。

这需要 Java 类的完全限定名和可选的返回类型。不幸的是,目前它只能在SQL语句中使用(或带有/ ),并且需要Java:nameexprselectExprorg.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|
## +------+

版本独立

我不会说它得到了支持,但这肯定是可能的。PySpark中目前可用的所有SQL函数都只是围绕Scala API的包装器。

假设我想重用我创建的UDAF作为SPARK SQL替代mysql的答案,GROUP_CONCAT聚合函数,它位于一个包中:GroupConcatcom.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|
## +---+---------+

对于我的口味来说,有太多的前导下划线,但正如你所看到的,这是可以做到的。

相关内容:


答案 2