使用udf和递归在数据框中创建新列

时间:2018-07-11 13:17:15

标签: scala apache-spark recursion parquet

我有两个镶木地板文件,一个描述具有inode编号的文件,一个描述inode名称和父inode,我需要从第二个文件中重建全路径。

我的带有inode描述的表名为idirs_table_read,其格式如下(这是一个完整的示例):

iparent,iname,ichild
93767723,folder12,40715069
65688175,level4,93767723
80373386,name,65688175
22746413,level2,80373386
24,base,22746413

我希望使用一个inode编号能够重建文件路径。
例如,对于inode 93767723,路径为:/base/level2/name/level4
我定义了两个函数(一个递归,另一个是过程性的),这两个函数在像这样newPathRecursive(1236549)时使用时有效,但是在withColumns中使用时却失败了:

def newPathRecursive( inumber : Int ):String = {
    var composite = ""
    var result = idirs_table_read.select("iparent", "iname").filter($"ichild"===inumber)

    if ( (result.count() == 1) && (result.first()(0) !=  inumber) )   {
       var num= result.first()(0).asInstanceOf[Int]
       composite=  newPath(num) + "/"  + result.first()(1).asInstanceOf[String] 
    }
    return composite
}


def newPathProcedurale  (inumber : Int ):String =  {

    var composite = ""
    var go = true
    var parentInode=inumber
    while(go){

        var result = idirs_table_read.select("iparent", "iname").filter($"ichild"===parentInode)

        if ( (result.count() == 1) && (result.first()(0) !=  inumber) )   {
            println(result.first()(0)+","+ result.first()(1)+","+ parentInode)
            parentInode = result.first()(0).asInstanceOf[Int]
            composite=  "/"  + result.first()(1).asInstanceOf[String] + composite
        }else{
            go=false
        }
    }
    return composite.asInstanceOf[String]
}
val buildpath2 = udf[String, Int](newPath2)
val buildpath = udf[String, Int](newPath)

我的目标是能够通过此路径替换另一个表中的inode编号,但是当我尝试在select中使用该函数时,我得到的是这样的:

 df.withColumn("newcol",buildpath ( $"inumber" )
 Caused by: java.lang.reflect.InvocationTargetException: org.apache.spark.SparkException: Job aborted due to stage failure: Task 0 in stage 1521.0 failed 4 times, most recent failure: Lost task 0.3 in stage 1521.0 (TID 14859, ip.ip.ip.ip, executor 1): org.apache.spark.SparkException: Failed to execute user defined function($anonfun$1: (int) => string)

能否请您帮助我编写这段代码,并最终建议我更好地实现该算法并更好地使用它?
我的目标只是简单地从具有完整路径的这两个文件中构建一个新的实木复合地板文件,而不是索引节点(这不是人类可读的)

1 个答案:

答案 0 :(得分:0)

由于帖子中提到的重复实际上与我的重复不同,并且我不理解其解释,因为真正的答案不在评论中,而实际上是答案。

如果udf内部使用的数据集不是本地的,我想做的事是不可能的:

inodes_table_read.isLocal
false

因此,我将使用其他内容,并将发布说明。