You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PySpark DataFrame去重:保留最新start_date行及所有列

PySpark去重并保留所有列(按最新start_date)

需求说明

当employee_name和department同时相同时视为重复行,仅保留start_date最新的一行,且需保留所有列数据。

原始DataFrame

employee_name   department      start_date                  favorite_color
---------------------------------------------------------------------------
James           sales           2023-11-03T12:38:02.371076Z green
James           sales           2020-01-03T12:38:02.371076Z red
Fred            operations      2023-09-27T16:28:01.920063Z red
Fred            leadership      2023-07-04T16:28:01.920063Z green
Fred            operations      2023-10-27T16:28:01.920063Z green
Wilma           administrative  2021-06-17T16:28:01.920063Z green

尝试的方法及问题

使用groupBy+agg(max(start_date))只能获取每组最新日期,但丢失了favorite_color等其他列:

deduped_df = employee_df.groupBy(col("employee_name"), col("department")).agg(max(col("start_date")))

得到的结果:

employee_name   department      start_date                  
-----------------------------------------------------------
Fred            leadership      2023-07-04T16:28:01.920063Z
Fred            operations      2023-10-27T16:28:01.920063Z
James           sales           2023-11-03T12:38:02.371076Z
Wilma           administrative  2021-06-17T16:28:01.920063Z

解决方案

方法一:使用窗口函数(推荐)

通过窗口函数按分组字段分区,对start_date降序排序后取每组第一行,完整保留所有列:

from pyspark.sql import Window
from pyspark.sql.functions import row_number, col

# 定义窗口规则:按employee_name和department分组,start_date降序排列
window_spec = Window.partitionBy("employee_name", "department").orderBy(col("start_date").desc())

# 添加行号字段,筛选出每组第一行后删除行号
deduped_df = employee_df.withColumn("row_num", row_number().over(window_spec)) \
                        .filter(col("row_num") == 1) \
                        .drop("row_num")

# 查看结果
deduped_df.show()

最终结果:

employee_name   department      start_date                  favorite_color
---------------------------------------------------------------------------
James           sales           2023-11-03T12:38:02.371076Z green
Fred            leadership      2023-07-04T16:28:01.920063Z green
Fred            operations      2023-10-27T16:28:01.920063Z green
Wilma           administrative  2021-06-17T16:28:01.920063Z green

注意:如果同一分组内有多个行的start_date完全相同(并列最新),row_number()会随机保留其中一行。若需保留所有并列最新行,可改用rank()或dense_rank()代替row_number()。

方法二:关联原表找回字段

先通过groupBy获取每组最新日期,再关联原表匹配完整行数据:

# 第一步:获取每组最新的start_date
latest_dates = employee_df.groupBy("employee_name", "department") \
                          .agg(max("start_date").alias("latest_start_date"))

# 第二步:关联原表,筛选出匹配的完整行
deduped_df = employee_df.join(
    latest_dates,
    (employee_df.employee_name == latest_dates.employee_name) &
    (employee_df.department == latest_dates.department) &
    (employee_df.start_date == latest_dates.latest_start_date),
    "inner"
).drop(latest_dates.employee_name, latest_dates.department, latest_dates.latest_start_date)

这种方法会保留所有start_date并列最新的行,适合需要保留全部并列记录的场景。


内容的提问来源于stack exchange,提问作者ChadSC

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 01:42:45