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

如何删除PySpark DataFrame中重复Name且Code为Null的记录?

解决PySpark DataFrame按Name去重并保留有效Code行的问题

没问题,这个需求用PySpark的窗口函数就能完美解决,我来一步步给你演示怎么做:

首先先确认下你的原始数据和DataFrame结构,你给出的代码是这样的:

# Prepare Data
data = [('Italy', 'ITA'), \
    ('China', 'CHN'), \
    ('China', None), \
    ('France', 'FRA'), \
    ('Spain', None), \
    ('Taiwan', 'TWN'), \
    ('Taiwan', None)
  ]

# Create DataFrame
columns = ['Name', 'Code']
df = spark.createDataFrame(data = data, schema = columns)
df.show(truncate=False)

运行后会得到原始的DataFrame,里面存在Name重复且对应Code为Null的行。

实现思路

我们的目标是:

  • 对于Name重复出现的分组,只保留其中Code不为Null的那一行
  • 对于Name只出现一次的行,不管Code是否为Null都保留
  • 最终每个Name只留一条记录

核心是用窗口函数给每个Name分组的行做排序标记,优先保留Code非Null的行,然后只取每个分组的第一行。

完整代码实现

from pyspark.sql.window import Window
import pyspark.sql.functions as F

# 定义窗口:按Name分组,排序规则是Code非Null的行优先排在前面
window_spec = Window.partitionBy("Name").orderBy(
    F.when(F.col("Code").isNotNull(), 0).otherwise(1)
)

# 添加行号列,每个Name分组内按排序规则生成行号
df_with_row_num = df.withColumn("row_num", F.row_number().over(window_spec))

# 过滤出每个分组的第一行,就是我们需要保留的记录
result_df = df_with_row_num.filter(F.col("row_num") == 1).drop("row_num")

# 查看结果
result_df.show(truncate=False)

结果说明

运行上面的代码后,你会得到期望的输出:

NameCode
ItalyITA
ChinaCHN
FranceFRA
Spainnull
TaiwanTWN

这里的逻辑是:

  1. 窗口函数按Name分组,排序时用when表达式给Code非Null的行标记为0,Null的标记为1,这样非Null的行就会排在分组的最前面
  2. row_number()会给每个分组内的行按排序顺序生成1、2、3...的行号
  3. 过滤row_num=1的行,就保证了每个Name只留一行——如果有非Null的Code就留那行,没有的话就留唯一的那行(比如Spain)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 00:00:56