Как получить разницу между двумя DataFrames?
В SparkSQL
1.6 API (scala) Dataframe
есть функции для пересечения и кроме, но не для разницы. Очевидно, что комбинация union и except может использоваться для генерации разности:
df1.except(df2).union(df2.except(df1))
Но это кажется немного неудобным. По моему опыту, если что-то кажется неудобным, есть лучший способ сделать это, особенно в Scala.
Ответы
Ответ 1
Вы всегда можете переписать его как:
df1.unionAll(df2).except(df1.intersect(df2))
Серьезно, хотя это UNION
, INTERSECT
и EXCEPT
/MINUS
в значительной степени является стандартным набором операторов объединения SQL. Я не знаю какой-либо системы, которая предоставляет XOR как операцию из коробки. Скорее всего, потому что тривиально реализовать с помощью других трех, и там не так много оптимизировать.
Ответ 2
почему не ниже?
df1.except(df2)
Ответ 3
Обратите внимание, что 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
Ответ 4
Если вы ищете решение Pyspark, вам следует использовать subtract() docs.
Кроме того, unionAll устарело в 2.0, вместо этого используйте union().
df1.union(df2).subtract(df1.intersect(df2))
Ответ 5
Я думаю, что было бы эффективнее использовать left join и затем отфильтровывать пустые значения.
df1.join(df2, Seq("some_join_key", "some_other_join_key"),"left")
.where(col("column_just_present_in_df2").isNull)