如何在Spark中集成Python映射,广播变量和Scala UDF

时间:2019-05-14 00:17:42

标签: scala apache-spark pyspark user-defined-functions

我有一个主要基于Python的笔记本,现在我想集成一些Scala UDF功能(出于性能原因实际上是从Python移植的)

这些UDF大量使用Python映射,因此我需要一种将这些映射从Python导入JVM的方法。我不是天生的Scala专家,我天真的认为我可以在程序包中编写一个Scala类,然后从Python使用它:

%scala

package com.scalatest

import org.apache.spark.sql.expressions.UserDefinedFunction
import org.apache.spark.sql.functions._
import org.apache.spark.sql.DataFrame
import collection.mutable.HashMap
import org.apache.spark.api.java.JavaSparkContext
import org.apache.spark.sql.functions._

class ScalaSparkTest(jsc: JavaSparkContext, lookups: 
   java.util.HashMap[String,String]) extends Serializable
{
  val lookup = lookups
//  val lookup_bc = JavaSparkContext.toSparkContext(jsc).broadcast(lookups)

  def lookupUdf = udf((c: String) => lookup(c))

  def lookupTest(df: DataFrame, input_col: String, output_col: String):
    DataFrame = {
      return df.withColumn(output_col, lookupUdf(col(input_col)))
    }
}

还有Python:

from pyspark.sql import Row, Column, DataFrame

rows = []
lookups = {}

for i in range(10):
  c = str(i)
  lookups[c] = str(i*2)
  rows.append( (c,c) )
df = spark.createDataFrame(rows,['A','B'])

scalaTest = sc._jvm.com.scalatest.ScalaSparkTest(sc._jsc, lookups)
scalaTest.printType()
results = DataFrame(scalaTest.lookupTest(df._jdf,'A','C'),sqlContext)
results.show()

# ==> This is how i do it in Python
lookups_bc = sc.broadcast(lookups)

@pandas_udf(LongType())
def udf_pandas(c):
  return c.map(lookups_bc.value)

result = df.select("C", udf_pandas("A"))

现在,这一切都可以按预期工作,但是可以序列化整个类。我不想这样做,我只想传递我的查询并广播它们,而不必每次都向整个班级发送。

鉴于我拥有的代码,我该如何更改它,以便我只能广播查找内容,然后可以在UDF中使用它?在Python中,通过使用全局变量保存广播并让闭包对其进行排序,可以轻松实现这一点。使用Scala,包和类,我不知道如何获得所需的行为,因此欢迎任何示例。

注意::我知道查找可以作为内置函数使用,但用例比示例代码复杂。

更新:响应重复标记。我没有从PySpark调用Scala的问题,我不知道该怎么做是从PySpark在Scala中创建一个广播变量,然后可将其提供给软件包中的UDF。我有一个地图的Python列表,我希望这些地图在Scala中广播,然后可以通过我的UDF访问广播变量。我不知道如何构造我的Scala和/或与Python的交互

0 个答案:

没有答案