【问题标题】:How to return ListBuffer as a column from UDF using Spark Scala?如何使用 Spark Scala 从 UDF 中将 ListBuffer 作为列返回?
【发布时间】:2019-03-02 11:23:53
【问题描述】:

我正在尝试使用 UDF 并将 ListBuffer 作为 UDF 的一列返回,但出现错误。

我通过执行以下代码创建了 Df:

val df = Seq((1,"dept3@@rama@@kumar","dept3##rama#@kumar"), (2,"dept31@@rama1##kumar1","dept33##rama3#@kumar3")).toDF("id","str1","str2")
df.show()

如下图所示:

+---+--------------------+--------------------+
| id|                str1|                str2|
+---+--------------------+--------------------+
|  1|  dept3@@rama@@kumar|  dept3##rama#@kumar|
|  2|dept31@@rama1##ku...|dept33##rama3#@ku...|
+---+--------------------+--------------------+

根据我的要求,我必须使用我必须根据一些输入拆分上述列,所以我尝试了如下 UDF:

    def appendDelimiterError=udf((id: Int, str1: String, str2: String)=> {
            var lit = new ListBuffer[Any]()
            if(str1.contains("@@"){val a=str1.split("@@")}
            else if(str1.contains("##"){val a=str1.split("##")}
            else if(str1.contains("#&"){val a=str1.split("#&")}
            if(str2.contains("@@"){ val b=str2.split("@@")}
            else if(str2.contains("##"){ val b=str2.split("##") }
            else if(str1.contains("#@"){val b=str2.split("#@")}
            var tmp_row = List(a,"test1",b)
            lit +=tmp_row 
return lit 
})

我尝试通过执行以下代码来校准:

val df1=df.appendDelimiterError("newcol",appendDelimiterError(df("id"),df("str1"),df("str2"))

我收到错误“这是一个错误的调用”。我想使用 ListBuffer/list 来存储并返回调用位置。

我的预期输出将是:

+---+--------------------+------------------------+----------------------------------------------------------------------+ 
| id|                str1|                str2    |                               newcol                                 |
+---+--------------------+------------------------+----------------------------------------------------------------------+
|  1|  dept3@@rama@@kumar|  dept3##rama#@kumar    |ListBuffer(List("dept","rama","kumar"),List("dept3","rama","kumar"))  |
|  2|dept31@@rama1##kumar1|dept33##rama3#@kumar3  | ListBuffer(List("dept31","rama1","kumar1"),List("dept33","rama3","kumar3")) |                                          
+---+--------------------+------------------------+----------------------------------------------------------------------+

如何做到这一点?

【问题讨论】:

  • 我觉得我的分割方式更简单灵活。
  • 为什么需要 ListBuffer?因为我认为您正在尝试建立返回值。不需要。
  • 嗨@thebluephantom 感谢您的快速回复。我必须使用 udf 在拆分之前我还有其他一些逻辑,但是正如您提供的没有 UDf 的答案。请帮助我尝试使用 UDF 和 LisfBuffer 或字符串比如“111, cat, 666,@SAPRATE,222, fritz, 777”
  • 不需要。不知道为什么需要 Listbuffer。逻辑不正确。我的贡献到此结束,函数式编程。
  • 我没有注意到其他答案。你解决了吗?

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


【解决方案1】:

我自己的虚构数据的替代方案,您可以对其进行定制,并且没有 UDF:

import org.apache.spark.sql.functions.{col, udf}  
import org.apache.spark.sql.expressions._
import org.apache.spark.sql.functions._

val df = Seq(
  (1, "111@#cat@@666", "222@@fritz@@777"),
  (2, "AAA@@cat@@555", "BBB@@felix@@888"),
  (3, "HHH@@mouse@@yyy", "123##mickey#@ZZZ") 
 ).toDF("c0", "c1", "c2")

 val df2 = df.withColumn( "c_split", split(col("c1"), ("(@#)|(@@)|(##)|(#@)")  ))
          .union(df.withColumn("c_split", split(col("c2"), ("(@#)|(@@)|(##)|(#@)")  )) )
 df2.show(false)
 df2.printSchema()


 val df3 = df2.groupBy(col("c0")).agg(collect_list(col("c_split")).as("List_of_Data") )   
 df3.show(false)
 df3.printSchema()

给出答案但没有 ListBuffer - 真的有必要吗?,如下:

+---+---------------+----------------+------------------+
|c0 |c1             |c2              |c_split           |
+---+---------------+----------------+------------------+
|1  |111@#cat@@666  |222@@fritz@@777 |[111, cat, 666]   |
|2  |AAA@@cat@@555  |BBB@@felix@@888 |[AAA, cat, 555]   |
|3  |HHH@@mouse@@yyy|123##mickey#@ZZZ|[HHH, mouse, yyy] |
|1  |111@#cat@@666  |222@@fritz@@777 |[222, fritz, 777] |
|2  |AAA@@cat@@555  |BBB@@felix@@888 |[BBB, felix, 888] |
|3  |HHH@@mouse@@yyy|123##mickey#@ZZZ|[123, mickey, ZZZ]|
+---+---------------+----------------+------------------+

root
 |-- c0: integer (nullable = false)
 |-- c1: string (nullable = true)
 |-- c2: string (nullable = true)
 |-- c_split: array (nullable = true)
 |    |-- element: string (containsNull = true)

 +---+---------------------------------------+
 |c0 |List_of_Data                           |
 +---+---------------------------------------+
 |1  |[[111, cat, 666], [222, fritz, 777]]   |
 |3  |[[HHH, mouse, yyy], [123, mickey, ZZZ]]|
 |2  |[[AAA, cat, 555], [BBB, felix, 888]]   |
 +---+---------------------------------------+

 root
  |-- c0: integer (nullable = false)
  |-- List_of_Data: array (nullable = true)
  |    |-- element: array (containsNull = true)
  |    |    |-- element: string (containsNull = true)

【讨论】:

    猜你喜欢
    • 2017-05-21
    • 1970-01-01
    • 1970-01-01
    • 2017-11-01
    • 2018-09-17
    • 1970-01-01
    • 1970-01-01
    • 2011-09-28
    • 2019-04-30
    相关资源
    最近更新 更多