在Spark
1.6 API(Scala)中,Dataframe
具有用于交集和除外的函数,但没有用于差异的函数。显然,并集和例外的组合可以用来产生差异:
df1.except(df2).union(df2.except(df1))
但这似乎有点尴尬。根据我的经验,如果有些事情看起来很尴尬,有更好的方法可以做到,尤其是在Scala中。
您可以随时将其重写为:
df1.unionAll(df2).except(df1.intersect(df2))
说真的,尽管这个UNION
、INTERSECT
和EXCEPT
/MINUS
基本上是一组标准的SQL组合运算符。我不知道有任何系统可以开箱即用地提供类似XOR的操作。很可能是因为使用其他三种方法实现起来很琐碎,而且没有太多需要优化的地方。
为什么不在下面?
df1.except(df2)
如果您正在寻找Pyspark解决方案,您应该使用减法()文档。
此外,unionAll在2.0中已弃用,请改用union()。
df1.union(df2).subtract(df1.intersect(df2))
请注意,EXCEPT(或MINUS,它只是EXCEPT的别名)的重复数据消除结果。因此,如果您希望"except"集(您提到的diff)+"intersect"集等于原始数据帧,请考虑这个保持重复的功能请求:
https://issues.apache.org/jira/browse/SPARK-21274
正如我在那里所写的,"EXCEPT ALL"可以在Spark SQL中重写为
SELECT a,b,c
FROM tab1 t1
LEFT OUTER JOIN
tab2 t2
ON (
(t1.a, t1.b, t1.c) = (t2.a, t2.b, t2.c)
)
WHERE
COALESCE(t2.a, t2.b, t2.c) IS NULL
我认为使用左联接然后过滤掉null会更有效。
df1.join(df2, Seq("some_join_key", "some_other_join_key"),"left")
.where(col("column_just_present_in_df2").isNull)