Spark sqlデータフレームがあり、ID
列とn
"data"列で構成されています。
_id | dat1 | dat2 | ... | datn
_
id
列は一意に決定されますが、_dat1 ... datn
_を見ると重複している可能性があります。
私の目標は、それらの重複のid
sを見つけることです。
これまでの私のアプローチ:
groupBy
を使用して重複行を取得します:
dup_df = df.groupBy(df.columns[1:]).count().filter('count > 1')
_dup_df
_をdf
全体と結合して、重複する行を取得しますincludeid
:
df.join(dup_df, df.columns[1:])
これは基本的に正しいと確信しています。_dat1 ... datn
_列にnull
値が含まれているため失敗します。
join
の値に対してnull
を実行するには、.eg this SO post 。しかし、これには巨大な値を作成する必要があります。 「文字列結合条件」。
したがって、私の質問:
joins
値に対してnull
を実行するための単純な/より一般的な/よりPythonicな方法はありますか?id
sを取得するための別の(より簡単で、より美しい、...)方法はありますか?ところで:私はSpark 2.1.0およびPython 3.5.3を使用しています
グループあたりの数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
を2回適用する(またはjoin
を使用する)ことができます。
グループごとに最小限の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
列を使用できます。