在UDF

时间:2017-07-19 15:09:59

标签: scala spark-dataframe user-defined-functions

我对于Object Orientend和功能性编程都很新,所以如果我在这里问一个愚蠢的问题,请原谅我。我已经彻底搜查并试图找到自己几个小时的答案,但无济于事。

我在scala上使用Spark2时遇到以下问题。

我有两个Dataframe,我想传递给UDF,它应该输出一个结果Dataframe。为了简单起见,我创造了两个" test"数据框作为输入。

val seqs = List(("1234","abaab"), ("1235","aaab")).toDF

val actions = List(1,2).toDF

动作列表数据框将转换为字符串数组,例如:

val actionsARR = actions.rdd.map(x=>(x.getInt(0)+96).toChar.toString).collect()

然后我们有一个UDF来计算seqs中动作的出现次数:

def countActions(sequence:String, actions:Array[String]):Array[Int] = {
  return actions.map(x => x.r.findAllIn(sequence).size)
}

放在一起:

val results = seqs.map(x=>(x.getString(0), countActions(x.getString(1),actionsARR))).toDF("sequence_u_key","action_counter")  

这在另一个运行一个命令的spark shell中工作正常,我现在尝试将代码嵌入到另一个接受Dataframes作为输入的UDF中:

def testFun(seqsin:DataFrame, actionsin:DataFrame ): DataFrame ={

seqsin.map(x=>(x.getString(0), countActions(x.getString(1),actionsARR))).toDF("sequence_u_key","action_counter")

}

用以下方式调用:

testFun(seqs,actions).show

有效,但它目前还没有使用Dataframe actionsin,但已经从中创建了名为actionsARR的数组。

当然我希望它在Dataframe中执行操作并将其转换为UDF中的Array,所以我尝试了:

def testFun(seqsin:DataFrame, actionsin:DataFrame ): DataFrame ={

val acts = actionsin.rdd.map(y=>(y.getInt(0)+96).toChar.toString).collect()

seqsin.map(x=>(x.getString(0), countActions(x.getString(1),acts))).toDF("sequence_u_key","action_counter")

}

但是当我用我的数据帧作为输入调用该函数时,我得到:

  

testFun(seqs,actions).show 17/07/19 07:31:32 ERROR Executor:Exception   在阶段38.0中的任务0.0(TID 64)java.lang.ClassCastException   17/07/19 07:31:32 WARN TaskSetManager:阶段38.0中丢失了任务0.0   (TID 64,localhost,executor driver):java.lang.ClassCastException

     

17/07/19 07:31:32 ERROR TaskSetManager:阶段38.0中的任务0失败1   倍;中止工作17/07/19 07:31:32 WARN TaskSetManager:丢失任务   阶段38.0中的1.0(TID 65,localhost,执行程序驱动程序):TaskKilled(故意杀死)org.apache.spark.SparkException:作业已中止   由于阶段失败:阶段38.0中的任务0失败1次,最近一次   失败:阶段38.0中丢失的任务0.0(TID 64,localhost,执行者   driver):java.lang.ClassCastException

     

驱动程序堆栈跟踪:at   org.apache.spark.scheduler.DAGScheduler.org $阿帕奇$火花$ $调度$$ DAGScheduler failJobAndIndependentStages(DAGScheduler.scala:1435)   在   org.apache.spark.scheduler.DAGScheduler $$ anonfun $ abortStage $ 1.适用(DAGScheduler.scala:1423)   在   org.apache.spark.scheduler.DAGScheduler $$ anonfun $ abortStage $ 1.适用(DAGScheduler.scala:1422)   在   scala.collection.mutable.ResizableArray $ class.foreach(ResizableArray.scala:59)   在scala.collection.mutable.ArrayBuffer.foreach(ArrayBuffer.scala:48)   在   org.apache.spark.scheduler.DAGScheduler.abortStage(DAGScheduler.scala:1422)   在   org.apache.spark.scheduler.DAGScheduler $$ anonfun $ handleTaskSetFailed $ 1.适用(DAGScheduler.scala:802)   在   org.apache.spark.scheduler.DAGScheduler $$ anonfun $ handleTaskSetFailed $ 1.适用(DAGScheduler.scala:802)   在scala.Option.foreach(Option.scala:257)at   org.apache.spark.scheduler.DAGScheduler.handleTaskSetFailed(DAGScheduler.scala:802)   在   org.apache.spark.scheduler.DAGSchedulerEventProcessLoop.doOnReceive(DAGScheduler.scala:1650)   在   org.apache.spark.scheduler.DAGSchedulerEventProcessLoop.onReceive(DAGScheduler.scala:1605)   在   org.apache.spark.scheduler.DAGSchedulerEventProcessLoop.onReceive(DAGScheduler.scala:1594)   在org.apache.spark.util.EventLoop $$ anon $ 1.run(EventLoop.scala:48)
  在   org.apache.spark.scheduler.DAGScheduler.runJob(DAGScheduler.scala:628)   在org.apache.spark.SparkContext.runJob(SparkContext.scala:1918)at   org.apache.spark.SparkContext.runJob(SparkContext.scala:1931)at at   org.apache.spark.SparkContext.runJob(SparkContext.scala:1944)at at   org.apache.spark.SparkContext.runJob(SparkContext.scala:1958)at at   org.apache.spark.rdd.RDD $$ anonfun $ collect $ 1.apply(RDD.scala:935)at at   org.apache.spark.rdd.RDDOperationScope $ .withScope(RDDOperationScope.scala:151)   在   org.apache.spark.rdd.RDDOperationScope $ .withScope(RDDOperationScope.scala:112)   在org.apache.spark.rdd.RDD.withScope(RDD.scala:362)at   org.apache.spark.rdd.RDD.collect(RDD.scala:934)at   testFun(:44)... 52 elided由以下原因引起:   java.lang.ClassCastException

也许我尝试将两个Dataframe传递给一个函数,将一个Dataversion转换为一个数组,然后在函数中使用它们,从根本上做了一些错误的事情?或许我错过了一些简单的东西?

哦,我可以成功创建一个函数,它接受一个Dataframe并转换并将其作为数组返回。

任何帮助将不胜感激

最好的问候

詹姆斯

0 个答案:

没有答案