Получить идентификаторы для повторяющихся строк (с учетом всех других столбцов) в Apache Spark

у меня есть фрейм данных sql Spark, состоящий из и n столбцы "данные", т. е.

id | dat1 | dat2 | ... | datn

на id columnn однозначно определяется, тогда как, глядя на dat1 ... datn там могут быть дубликаты.

моя цель-найти ids этих дубликатов.

мой подход до сих пор:

  • получить дубликаты строк с помощью groupBy:

    dup_df = df.groupBy(df.columns[1:]).count().filter('count > 1')

  • Регистрация the dup_df С df чтобы получить дубликаты строк в том числе id:

    df.join(dup_df, df.columns[1:])

Я совершенно уверен, что это в основном правильно, это не удается, потому что dat1 ... datn столбцы содержат null значения.

сделать join on null значения, я нашел .е.г это так пост. Но для этого потребуется построить огромное "условие соединения строк".

мой вопросы:
  1. есть ли простой / более общий / более питонический способ сделать joins on null значения?
  2. или, еще лучше, есть другой (проще, красивее,...) метод получения желаемого ids?

BTW: я использую Spark 2.1.0 и Python 3.5.3

1 ответов


если количество ids в группе относительно невелико, вы можете groupBy и collect_list. Необходимый импорт

from pyspark.sql.functions import collect_list, size

пример:

df = sc.parallelize([
    (1, "a", "b", 3),
    (2, None, "f", None),
    (3, "g", "h", 4),
    (4, None, "f", None),
    (5, "a", "b", 3)
]).toDF(["id"])

запрос:

(df
   .groupBy(df.columns[1:])
   .agg(collect_list("id").alias("ids"))
   .where(size("ids") > 1))

и в итоге:

+----+---+----+------+
|  _2| _3|  _4|   ids|
+----+---+----+------+
|null|  f|null|[2, 4]|
|   a|  b|   3|[1, 5]|
+----+---+----+------+

вы можете подать заявку explode дважды (или используйте udf) в выходной эквивалентен вернулся из join.

вы также можете идентифицировать группы, используя minimal id в группе. Несколько дополнительных импорт:

from pyspark.sql.window import Window
from pyspark.sql.functions import col, count, min

окне определение:

w = Window.partitionBy(df.columns[1:])

запрос:

(df
    .select(
        "*", 
        count("*").over(w).alias("_cnt"), 
        min("id").over(w).alias("group"))
    .where(col("_cnt") > 1))

и в итоге:

+---+----+---+----+----+-----+
| id|  _2| _3|  _4|_cnt|group|
+---+----+---+----+----+-----+
|  2|null|  f|null|   2|    2|
|  4|null|  f|null|   2|    2|
|  1|   a|  b|   3|   2|    1|
|  5|   a|  b|   3|   2|    1|
+---+----+---+----+----+-----+

вы можете использовать group столбец для самостоятельного соединения.