【问题标题】:How to obtain the symmetric difference between two DataFrames?如何获得两个 DataFrame 之间的对称差异?
【发布时间】:2016-07-12 00:38:23
【问题描述】:

在SparkSQL 1.6 API (scala) 中Dataframe 具有相交和除外功能,但没有差异功能。显然,union 和 except 的组合可以用来产生差异:

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

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

【问题讨论】:

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


【解决方案1】:

您可以随时将其重写为:

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

说真的,尽管UNION、INTERSECT 和 EXCEPT / MINUS 几乎是一组标准的 SQL 组合运算符。我不知道有任何系统提供开箱即用的 XOR 类操作。很可能是因为使用其他三个实现起来很简单,而且那里没有太多需要优化的地方。

【讨论】:

  • 谢谢。如果它在那里,它可能会在幕后做这样的事情。
【解决方案2】:

为什么不是下面?

df1.except(df2)

【讨论】:

  • 因为它不执行 XOR。我正在寻找不在交叉点的所有元素。您的代码仅返回 d1 中不在交集中的元素。我还需要 d2 中不在交叉路口的那些。
【解决方案3】:

如果您正在寻找 Pyspark 解决方案,您应该使用 subtract() docs。

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

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

【讨论】:

  • 这被否决的任何原因? pyspark 没有except(),但有subtract(),这似乎与批准的解决方案中提供的功能相似。
  • 没有意识到给出了-1。是的,我也有兴趣了解它被否决的原因
【解决方案4】:

请注意,EXCEPT(或 MINUS,它只是 EXCEPT 的别名)重复数据删除结果。因此,如果您希望“除外”集(您提到的差异)+“相交”集等于原始数据帧,请考虑保留重复的此功能请求:

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) 不喜欢重复。为了这个问题,这里的 DF 可以被认为是集合。 2)最初的问题是针对 Spark,而不是 SparkSQL。我更喜欢功能风格的编码。
【解决方案5】:

我认为使用左连接然后过滤掉空值会更有效。

df1.join(df2, Seq("some_join_key", "some_other_join_key"),"left")
.where(col("column_just_present_in_df2").isNull)

【讨论】:

    猜你喜欢
    • 2018-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-09-22
    • 2022-11-27
    相关资源
    最近更新 更多