如何获得两个数据帧之间的对称差异?

问题描述 投票:23回答:5

SparkSQL 1.6 API(标量)中,Dataframe具有用于相交和除的功能,但不具有相差的功能。显然,联合和除外的组合可以用来产生差异:

df1.except(df2).union(df2.except(df1))

但是这似乎有点尴尬。以我的经验,如果有些事情看起来很尴尬,那么有更好的方法可以做到这一点,尤其是在Scala中。

scala apache-spark apache-spark-sql
5个回答
37
投票

您始终可以将其重写为:

df1.unionAll(df2).except(df1.intersect(df2))

虽然很严重,但是UNIONINTERSECTEXCEPT / MINUS几乎是一组标准的SQL组合运算符。我不知道任何提供开箱即用的XOR之类的系统的系统。最有可能的原因是,使用其他三个实现起来并不容易,并且在那里没有太多要优化的地方。


6
投票

为什么不下面?

df1.except(df2)

2
投票

注意EXCEPT(或MINUS只是EXCEPT的别名)会对结果进行去重复。因此,如果您希望“ except”集(您提到的差异)+“ 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

-1
投票

如果您正在寻找Pyspark解决方案,则应使用减去()docs

此外,unionAll在2.0中已弃用,请改用union()。

df1.union(df2).subtract(df1.intersect(df2))


-2
投票

我认为使用左联接然后过滤出空值可能会更有效。

df1.join(df2, Seq("some_join_key", "some_other_join_key"),"left")
.where(col("column_just_present_in_df2").isNull)
© www.soinside.com 2019 - 2024. All rights reserved.