我有一个包含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的多个例子。但是根据不能修改。
答案 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")