[英]Filter a grouped dataframe based on column value in pyspark
我有低於df。 我想按公司和日期對 dataframe 進行分組,並且對於此類分組的子集,如果可用,則根據優先級 QF 的類別過濾行,如果不是 SAF,如果不是,則為 AF。 我正在嘗試使用 window function 分配等級,但也許有更簡單的方法。
company date value category
------------------------------------
xyz 31-12-2020 12 AF
xyz 31-12-2020 10 SAF
xyz 31-12-2020 11 QF
xyz 30-06-2020 14 AF
xyz 30-06-2020 16 SAF
xyz 30-09-2020 13 SAF
xyz 31-03-2019 20 AF
預期 output:
company date value category
------------------------------------
xyz 31-12-2020 11 QF
xyz 30-06-2020 16 SAF
xyz 30-09-2020 13 SAF
xyz 31-03-2019 20 AF
我們可以使用when().otherwise()
為類別分配排名,並保留組中排名最低的記錄。
data_sdf. \
withColumn('cat_rank',
func.when(func.col('cat') == 'QF', func.lit(1)).
when(func.col('cat') == 'SAF', func.lit(2)).
when(func.col('cat') == 'AF', func.lit(3))
). \
withColumn('min_cat_rank',
func.min('cat_rank').over(wd.partitionBy('company', 'dt'))
). \
filter(func.col('min_cat_rank').isNotNull()). \
filter(func.col('min_cat_rank') == func.col('cat_rank')). \
drop('cat_rank', 'min_cat_rank'). \
show()
# +-------+----------+---+---+
# |company| dt|val|cat|
# +-------+----------+---+---+
# | xyz|30-09-2020| 13|SAF|
# | xyz|30-06-2020| 16|SAF|
# | xyz|31-03-2019| 20| AF|
# | xyz|31-12-2020| 11| QF|
# +-------+----------+---+---+
假設只有有限數量的類別,並且每個類別沒有重復的條目,我建議 map 將類別轉換為整數,您可以對其進行排序。 之后,您可以簡單地分區、排序並選擇每個分區的第一個條目。
df = df.withColumn('mapping',
f.when(f.col('category') == 'QF', f.lit('1')).otherwise(
f.when(f.col('category') == 'SAF', f.lit('2')).otherwise(
f.when(f.col('category') == 'AF', f.lit('3')).otherwise(f.lit(None)))))
w = Window.partitionBy('date').orderBy(f.col('mapping'))
df.withColumn('row', f.row_number().over(w))\
.filter(f.col('row') == 1)\
.drop('row', 'mapping')\
.show()
假設在company
和date
的組合中同一類別可以有多個值,並且我們希望保留首選類別的value
,這是一個具有兩個 window 函數的解決方案:
import pyspark.sql.functions as F
from pyspark.sql.window import Window
w_company_date = Window.partitionBy('company', 'date')
w_company_date_category = Window.partitionBy('company', 'date', 'category')
df = (df
.withColumn('priority', F.when(F.col('category') == 'QF', 1)
.when(F.col('category') == 'SAF', 2)
.when(F.col('category') == 'AF', 3)
.otherwise(None))
.withColumn('top_choice', F.when((F.col('priority') == F.min('priority').over(w_company_date))
& (F.col('value') == F.max('value').over(w_company_date_category)), 1)
.otherwise(0))
.filter(F.col('top_choice') == 1)
.drop('priority', 'top_choice')
)
df.show()
+-------+----------+-----+--------+
|company| date|value|category|
+-------+----------+-----+--------+
| xyz|2020-03-31| 20| AF|
| xyz|2020-06-30| 16| SAF|
| xyz|2020-09-30| 13| SAF|
| xyz|2020-12-31| 11| QF|
+-------+----------+-----+--------+
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.