web-dev-qa-db-ja.com

spark別のデータフレームの値に基づいて行をフィルタリング(削除)する]

> 20列の「大きな」データセット(_huge_df_)があります。列の1つはidフィールドです(pyspark.sql.functions.monotonically_increasing_id()で生成)。

いくつかの基準を使用して、2番目のデータフレーム(_filter_df_)を生成します。これは、_huge_df_から後でフィルタリングするid値で構成されます。

現在私はこれを行うためにSQL構文を使用しています:

_filter_df.createOrReplaceTempView('filter_view')
huge_df = huge_df.where('id NOT IN (SELECT id FROM filter_view)')
_

質問1: Pythonのみを使用して、つまりTempViewを登録する必要なしに、これを行う方法はありますか?

質問2:同じことを達成するための完全に異なる方法はありますか?

8
Tw UxTLi51Nus

JOINを使用できます

huge_df = huge_df.join(filter_df, huge_df.id == filter_df.id, "left_outer")
                 .where(filter_df.id.isNull())
                 .select([col(c) for c in huge_df.columns]

ただし、高価なシャッフルが発生します。

ロジックは単純です。idフィールドでfilter_dfを使用して左結合を行い、filter_dfがnullかどうかを確認します-nullの場合、filter_dfにそのような行がないことを意味します

9
T. Gawęda

これを行う別の方法があります-

# Sample data
hugedf = spark.createDataFrame([[1,'a'],[2,'b'],[3,'c'],[4,'d']],schema=(['k1','v1']))
fildf = spark.createDataFrame([[1,'b'],[3,'c']],schema=(['k2','v2']))


from pyspark.sql.functions import col
hugedf\
.select('k1')\     
.subtract(fildf.select('k2'))\ 
.toDF('d1')\
.join(hugedf,col('d1')==hugedf.k1)\
.drop('d1')\
.show()

ロジックは単純です。hugeDFで見つかったID値からFilteredDfで見つかったID値を減算し、filterDFにないID値を残します。

わかりやすくするために、差し引いた値を列「d1」としてマークし、d1の値でhugeDFテーブルを結合し、d1をドロップして最終結果を出しました。

0
Pushkr