首页 > 解决方案 > Groupby 和 collect_list 基于 PySpark 中的另一列维护顺序

问题描述

我有一个像这样的 PySpark 数据框,

+----------+------------+------------+------------+
|   Name   |  dateCol1  |  dateCol2  |  dateCol3  |
+----------+------------+------------+------------+
| user1    | 2018-01-01 | 2018-01-10 | 2018-01-01 |
| user1    | 2018-01-11 | 2018-01-20 | 2018-01-01 |
| user2    | 2018-01-11 | 2018-01-20 | 2018-01-11 |
| user1    | 2019-01-21 | 2018-01-30 | 2018-01-01 |
+----------+------------+------------+------------+

我想在键、dateCol1 和 dateCol2 上对这个数据集进行分组,因此列名称上的 collect_list 。为此,我正在使用代码,

spark_df.groupBy('dateCol1', 'dateCol2').agg(F.collect_list('Name'))

在收集要列出的列时,我还想根据列 dateCol3 维护值的顺序。

例如,我想确保对于dateCol1 == '2018-01-11'and dateCol2 == '2018-01-20',收集到列表我总是会得到[user1, user2](基于 dateCol3 的顺序)。

数据帧所需的输出是,

+------------+------------+----------------+
|  dateCol1  |  dateCol2  |    List        |
+------------+------------+----------------+
| 2018-01-01 | 2018-01-10 | [user1]        |
| 2018-01-11 | 2018-01-20 | [user1, user2] |
| 2019-01-21 | 2018-01-30 | [user1]        |
+------------+------------+----------------+

collect_list 默认情况下不会保持顺序,如何确保收集的列表是基于数据框中的另一个外部列排序的?

标签: pythonpyspark

解决方案


你可以试试:

spark_df.orderBy('dateCol3', ascending=True).groupBy('dateCol1', 'dateCol2').agg(F.collect_list('Name'))

或者,虽然这有点矫枉过正,但您可以使用窗口:

from pyspark.sql import Window as w

spark_df.select('dateCol1', 'dateCol2', F.collect_list('Name').over(w.partitionBy(['dateCol1','dateCol2']).orderBy(F.col('dateCol3'))).alias('Name')).distinct()

推荐阅读