如何创建自定义用户定义的聚合不同功能

时间:2017-10-18 15:23:56

标签: scala apache-spark apache-spark-sql spark-dataframe

我有一个包含4列的数据框。

数据框示例

id1 id2 id3 id4
---------------
a1  a2  a3  a4
b1  b2  b3  b4
b1  b2  b3  b4
c1  c2  c3  c4
    b2      
c1
        a3
            a4
c1
        d4

一行中有两种类型的数据,要么所有列都有数据,要么只有一列。

我想对所有列执行不同的功能,例如在比较行之间的值时,它只会比较行中存在的值而不考虑空值。

输出数据框应为

id1 id2 id3 id4
a1  a2  a3  a4
b1  b2  b3  b4
c1  c2  c3  c4
        d4

我在火花中看过UDAF的多个例子。但是根据不能修改。

2 个答案:

答案 0 :(得分:1)

您可以将filter用于以下所有列

df.filter($"id1" =!= "" && $"id2" =!= "" && $"id3" =!= "" && $"id4" =!= "")

你应该得到你的最终数据帧。

以上代码适用于静态四列圆柱形数据帧。如果你有超过四列的方法会变得忙乱,因为你必须编写太多的逻辑检查。

解决方法是使用udf函数,如下所示

import org.apache.spark.sql.functions._
def checkIfNull = udf((co : mutable.WrappedArray[String]) => !(co.contains(null) || co.contains("")))
df.filter(checkIfNull(array(df.columns.map(col): _*))).show(false)

我希望答案很有帮助

答案 1 :(得分:1)

可以利用dropDuplicates依赖于顺序来解决此问题,请参阅答案here。但是,效率不高,应该有更有效的解决方案。

首先使用distinct()删除所有重复项,然后按每个列迭代排序并删除它的重复项。这些列按降序排列为nulls,然后放在最后。

四个静态列的示例:

val df2 = df.distinct()
  .orderBy($"id1".desc).dropDuplicates("id1")
  .orderBy($"id2".desc).dropDuplicates("id2")
  .orderBy($"id3".desc).dropDuplicates("id3")
  .orderBy($"id4".desc).dropDuplicates("id4")